all that is left to do is to actually perform the
[Samba.git] / source / printing / nt_printing.c
blob17a16b84bcef6277427d8233d59f1a91b4d42baa
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);
322 return True;
325 /*******************************************************************
326 tdb traversal function for counting printers.
327 ********************************************************************/
329 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
330 TDB_DATA data, void *context)
332 int *printer_count = (int*)context;
334 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
335 (*printer_count)++;
336 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
339 return 0;
342 /*******************************************************************
343 Update the spooler global c_setprinter. This variable is initialized
344 when the parent smbd starts with the number of existing printers. It
345 is monotonically increased by the current number of printers *after*
346 each add or delete printer RPC. Only Microsoft knows why... JRR020119
347 ********************************************************************/
349 uint32 update_c_setprinter(BOOL initialize)
351 int32 c_setprinter;
352 int32 printer_count = 0;
354 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
356 /* Traverse the tdb, counting the printers */
357 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
359 /* If initializing, set c_setprinter to current printers count
360 * otherwise, bump it by the current printer count
362 if (!initialize)
363 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
364 else
365 c_setprinter = printer_count;
367 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
368 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
370 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
372 return (uint32)c_setprinter;
375 /*******************************************************************
376 Get the spooler global c_setprinter, accounting for initialization.
377 ********************************************************************/
379 uint32 get_c_setprinter(void)
381 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
383 if (c_setprinter == (int32)-1)
384 c_setprinter = update_c_setprinter(True);
386 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
388 return (uint32)c_setprinter;
391 /****************************************************************************
392 Get builtin form struct list.
393 ****************************************************************************/
395 int get_builtin_ntforms(nt_forms_struct **list)
397 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
398 return sizeof(default_forms) / sizeof(default_forms[0]);
401 /****************************************************************************
402 get a builtin form struct
403 ****************************************************************************/
405 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
407 int i,count;
408 fstring form_name;
409 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
410 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
411 count = sizeof(default_forms) / sizeof(default_forms[0]);
412 for (i=0;i<count;i++) {
413 if (strequal(form_name,default_forms[i].name)) {
414 DEBUGADD(6,("Found builtin form %s \n", form_name));
415 memcpy(form,&default_forms[i],sizeof(*form));
416 break;
420 return (i !=count);
423 /****************************************************************************
424 get a form struct list
425 ****************************************************************************/
426 int get_ntforms(nt_forms_struct **list)
428 TDB_DATA kbuf, newkey, dbuf;
429 nt_forms_struct *tl;
430 nt_forms_struct form;
431 int ret;
432 int i;
433 int n = 0;
435 for (kbuf = tdb_firstkey(tdb_forms);
436 kbuf.dptr;
437 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
438 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
440 dbuf = tdb_fetch(tdb_forms, kbuf);
441 if (!dbuf.dptr) continue;
443 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
444 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
445 &i, &form.flag, &form.width, &form.length, &form.left,
446 &form.top, &form.right, &form.bottom);
447 SAFE_FREE(dbuf.dptr);
448 if (ret != dbuf.dsize) continue;
450 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
451 if (!tl) {
452 DEBUG(0,("get_ntforms: Realloc fail.\n"));
453 return 0;
455 *list = tl;
456 (*list)[n] = form;
457 n++;
461 return n;
464 /****************************************************************************
465 write a form struct list
466 ****************************************************************************/
467 int write_ntforms(nt_forms_struct **list, int number)
469 pstring buf, key;
470 int len;
471 TDB_DATA kbuf,dbuf;
472 int i;
474 for (i=0;i<number;i++) {
475 /* save index, so list is rebuilt in correct order */
476 len = tdb_pack(buf, sizeof(buf), "dddddddd",
477 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
478 (*list)[i].left, (*list)[i].top, (*list)[i].right,
479 (*list)[i].bottom);
480 if (len > sizeof(buf)) break;
481 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
482 kbuf.dsize = strlen(key)+1;
483 kbuf.dptr = key;
484 dbuf.dsize = len;
485 dbuf.dptr = buf;
486 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
489 return i;
492 /****************************************************************************
493 add a form struct at the end of the list
494 ****************************************************************************/
495 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
497 int n=0;
498 BOOL update;
499 fstring form_name;
500 nt_forms_struct *tl;
503 * NT tries to add forms even when
504 * they are already in the base
505 * only update the values if already present
508 update=False;
510 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
511 for (n=0; n<*count; n++) {
512 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
513 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
514 update=True;
515 break;
519 if (update==False) {
520 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
521 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
522 return False;
524 *list = tl;
525 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
526 (*count)++;
529 (*list)[n].flag=form->flags;
530 (*list)[n].width=form->size_x;
531 (*list)[n].length=form->size_y;
532 (*list)[n].left=form->left;
533 (*list)[n].top=form->top;
534 (*list)[n].right=form->right;
535 (*list)[n].bottom=form->bottom;
537 return True;
540 /****************************************************************************
541 delete a named form struct
542 ****************************************************************************/
543 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
545 pstring key;
546 TDB_DATA kbuf;
547 int n=0;
548 fstring form_name;
550 *ret = WERR_OK;
552 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
554 for (n=0; n<*count; n++) {
555 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
556 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
557 break;
561 if (n == *count) {
562 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
563 *ret = WERR_INVALID_PARAM;
564 return False;
567 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
568 kbuf.dsize = strlen(key)+1;
569 kbuf.dptr = key;
570 if (tdb_delete(tdb_forms, kbuf) != 0) {
571 *ret = WERR_NOMEM;
572 return False;
575 return True;
578 /****************************************************************************
579 update a form struct
580 ****************************************************************************/
581 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
583 int n=0;
584 fstring form_name;
585 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
587 DEBUG(106, ("[%s]\n", form_name));
588 for (n=0; n<count; n++)
590 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
591 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
592 break;
595 if (n==count) return;
597 (*list)[n].flag=form->flags;
598 (*list)[n].width=form->size_x;
599 (*list)[n].length=form->size_y;
600 (*list)[n].left=form->left;
601 (*list)[n].top=form->top;
602 (*list)[n].right=form->right;
603 (*list)[n].bottom=form->bottom;
606 /****************************************************************************
607 get the nt drivers list
609 traverse the database and look-up the matching names
610 ****************************************************************************/
611 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
613 int total=0;
614 fstring short_archi;
615 fstring *fl;
616 pstring key;
617 TDB_DATA kbuf, newkey;
619 get_short_archi(short_archi, architecture);
620 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
622 for (kbuf = tdb_firstkey(tdb_drivers);
623 kbuf.dptr;
624 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
625 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
627 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
628 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
629 return -1;
631 else *list = fl;
633 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
634 total++;
637 return(total);
640 /****************************************************************************
641 function to do the mapping between the long architecture name and
642 the short one.
643 ****************************************************************************/
644 BOOL get_short_archi(char *short_archi, char *long_archi)
646 struct table {
647 char *long_archi;
648 char *short_archi;
651 struct table archi_table[]=
653 {"Windows 4.0", "WIN40" },
654 {"Windows NT x86", "W32X86" },
655 {"Windows NT R4000", "W32MIPS" },
656 {"Windows NT Alpha_AXP", "W32ALPHA" },
657 {"Windows NT PowerPC", "W32PPC" },
658 {NULL, "" }
661 int i=-1;
663 DEBUG(107,("Getting architecture dependant directory\n"));
664 do {
665 i++;
666 } while ( (archi_table[i].long_archi!=NULL ) &&
667 StrCaseCmp(long_archi, archi_table[i].long_archi) );
669 if (archi_table[i].long_archi==NULL) {
670 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
671 return False;
674 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
676 DEBUGADD(108,("index: [%d]\n", i));
677 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
678 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
680 return True;
683 /****************************************************************************
684 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
685 There are two case to be covered here: PE (Portable Executable) and NE (New
686 Executable) files. Both files support the same INFO structure, but PE files
687 store the signature in unicode, and NE files store it as !unicode.
688 returns -1 on error, 1 on version info found, and 0 on no version info found.
689 ****************************************************************************/
691 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
693 int i;
694 char *buf;
695 ssize_t byte_count;
697 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
698 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
699 fname, PE_HEADER_SIZE));
700 goto error_exit;
703 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
704 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
705 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
706 fname, byte_count));
707 goto no_version_info;
710 /* Is this really a DOS header? */
711 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
712 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
713 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
714 goto no_version_info;
717 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
718 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
719 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
720 fname, errno));
721 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
722 goto no_version_info;
725 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
726 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
727 fname, byte_count));
728 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
729 goto no_version_info;
732 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
733 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
734 int num_sections;
735 int section_table_bytes;
737 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
738 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
739 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
740 /* At this point, we assume the file is in error. It still could be somthing
741 * else besides a PE file, but it unlikely at this point.
743 goto error_exit;
746 /* get the section table */
747 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
748 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
749 SAFE_FREE(buf);
750 if ((buf=malloc(section_table_bytes)) == NULL) {
751 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
752 fname, section_table_bytes));
753 goto error_exit;
756 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
757 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
758 fname, byte_count));
759 goto error_exit;
762 /* Iterate the section table looking for the resource section ".rsrc" */
763 for (i = 0; i < num_sections; i++) {
764 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
766 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
767 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
768 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
770 SAFE_FREE(buf);
771 if ((buf=malloc(section_bytes)) == NULL) {
772 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
773 fname, section_bytes));
774 goto error_exit;
777 /* Seek to the start of the .rsrc section info */
778 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
779 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
780 fname, errno));
781 goto error_exit;
784 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
785 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
786 fname, byte_count));
787 goto error_exit;
790 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
791 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
792 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
793 /* Align to next long address */
794 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
796 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
797 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
798 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
800 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
801 fname, *major, *minor,
802 (*major>>16)&0xffff, *major&0xffff,
803 (*minor>>16)&0xffff, *minor&0xffff));
804 SAFE_FREE(buf);
805 return 1;
812 /* Version info not found, fall back to origin date/time */
813 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
814 SAFE_FREE(buf);
815 return 0;
817 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
818 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
819 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
820 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
821 /* At this point, we assume the file is in error. It still could be somthing
822 * else besides a NE file, but it unlikely at this point. */
823 goto error_exit;
826 /* Allocate a bit more space to speed up things */
827 SAFE_FREE(buf);
828 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
829 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
830 fname, PE_HEADER_SIZE));
831 goto error_exit;
834 /* This is a HACK! I got tired of trying to sort through the messy
835 * 'NE' file format. If anyone wants to clean this up please have at
836 * it, but this works. 'NE' files will eventually fade away. JRR */
837 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
838 /* Cover case that should not occur in a well formed 'NE' .dll file */
839 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
841 for(i=0; i<byte_count; i++) {
842 /* Fast skip past data that can't possibly match */
843 if (buf[i] != 'V') continue;
845 /* Potential match data crosses buf boundry, move it to beginning
846 * of buf, and fill the buf with as much as it will hold. */
847 if (i>byte_count-VS_VERSION_INFO_SIZE) {
848 int bc;
850 memcpy(buf, &buf[i], byte_count-i);
851 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
852 (byte_count-i))) < 0) {
854 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
855 fname, errno));
856 goto error_exit;
859 byte_count = bc + (byte_count - i);
860 if (byte_count<VS_VERSION_INFO_SIZE) break;
862 i = 0;
865 /* Check that the full signature string and the magic number that
866 * follows exist (not a perfect solution, but the chances that this
867 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
868 * twice, as it is simpler to read the code. */
869 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
870 /* Compute skip alignment to next long address */
871 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
872 sizeof(VS_SIGNATURE)) & 3;
873 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
875 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
876 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
877 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
878 fname, *major, *minor,
879 (*major>>16)&0xffff, *major&0xffff,
880 (*minor>>16)&0xffff, *minor&0xffff));
881 SAFE_FREE(buf);
882 return 1;
887 /* Version info not found, fall back to origin date/time */
888 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
889 SAFE_FREE(buf);
890 return 0;
892 } else
893 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
894 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
895 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
897 no_version_info:
898 SAFE_FREE(buf);
899 return 0;
901 error_exit:
902 SAFE_FREE(buf);
903 return -1;
906 /****************************************************************************
907 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
908 share one or more files. During the MS installation process files are checked
909 to insure that only a newer version of a shared file is installed over an
910 older version. There are several possibilities for this comparison. If there
911 is no previous version, the new one is newer (obviously). If either file is
912 missing the version info structure, compare the creation date (on Unix use
913 the modification date). Otherwise chose the numerically larger version number.
914 ****************************************************************************/
915 static int file_version_is_newer(connection_struct *conn, fstring new_file,
916 fstring old_file)
918 BOOL use_version = True;
919 pstring filepath;
921 uint32 new_major;
922 uint32 new_minor;
923 time_t new_create_time;
925 uint32 old_major;
926 uint32 old_minor;
927 time_t old_create_time;
929 int access_mode;
930 int action;
931 files_struct *fsp = NULL;
932 SMB_STRUCT_STAT st;
933 SMB_STRUCT_STAT stat_buf;
934 BOOL bad_path;
936 ZERO_STRUCT(st);
937 ZERO_STRUCT(stat_buf);
938 new_create_time = (time_t)0;
939 old_create_time = (time_t)0;
941 /* Get file version info (if available) for previous file (if it exists) */
942 pstrcpy(filepath, old_file);
944 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
946 fsp = open_file_shared(conn, filepath, &stat_buf,
947 SET_OPEN_MODE(DOS_OPEN_RDONLY),
948 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
949 0, 0, &access_mode, &action);
950 if (!fsp) {
951 /* Old file not found, so by definition new file is in fact newer */
952 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
953 filepath, errno));
954 return True;
956 } else {
957 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
958 if (ret == -1) goto error_exit;
960 if (!ret) {
961 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
962 old_file));
963 use_version = False;
964 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
965 old_create_time = st.st_mtime;
966 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
969 close_file(fsp, True);
971 /* Get file version info (if available) for new file */
972 pstrcpy(filepath, new_file);
973 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
975 fsp = open_file_shared(conn, filepath, &stat_buf,
976 SET_OPEN_MODE(DOS_OPEN_RDONLY),
977 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
978 0, 0, &access_mode, &action);
979 if (!fsp) {
980 /* New file not found, this shouldn't occur if the caller did its job */
981 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
982 filepath, errno));
983 goto error_exit;
985 } else {
986 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
987 if (ret == -1) goto error_exit;
989 if (!ret) {
990 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
991 new_file));
992 use_version = False;
993 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
994 new_create_time = st.st_mtime;
995 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
998 close_file(fsp, True);
1000 if (use_version) {
1001 /* Compare versions and choose the larger version number */
1002 if (new_major > old_major ||
1003 (new_major == old_major && new_minor > old_minor)) {
1005 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1006 return True;
1008 else {
1009 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1010 return False;
1013 } else {
1014 /* Compare modification time/dates and choose the newest time/date */
1015 if (new_create_time > old_create_time) {
1016 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1017 return True;
1019 else {
1020 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1021 return False;
1025 error_exit:
1026 if(fsp)
1027 close_file(fsp, True);
1028 return -1;
1031 /****************************************************************************
1032 Determine the correct cVersion associated with an architecture and driver
1033 ****************************************************************************/
1034 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
1035 struct current_user *user, WERROR *perr)
1037 int cversion;
1038 int access_mode;
1039 int action;
1040 NTSTATUS nt_status;
1041 pstring driverpath;
1042 DATA_BLOB null_pw;
1043 files_struct *fsp = NULL;
1044 BOOL bad_path;
1045 SMB_STRUCT_STAT st;
1046 connection_struct *conn;
1048 ZERO_STRUCT(st);
1050 *perr = WERR_INVALID_PARAM;
1052 /* If architecture is Windows 95/98/ME, the version is always 0. */
1053 if (strcmp(architecture, "WIN40") == 0) {
1054 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1055 *perr = WERR_OK;
1056 return 0;
1060 * Connect to the print$ share under the same account as the user connected
1061 * to the rpc pipe. Note we must still be root to do this.
1064 /* Null password is ok - we are already an authenticated user... */
1065 null_pw = data_blob(NULL, 0);
1066 become_root();
1067 conn = make_connection_with_chdir("print$", null_pw, "A:", user->vuid, &nt_status);
1068 unbecome_root();
1070 if (conn == NULL) {
1071 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1072 *perr = ntstatus_to_werror(nt_status);
1073 return -1;
1076 /* We are temporarily becoming the connection user. */
1077 if (!become_user(conn, conn->vuid)) {
1078 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1079 *perr = WERR_ACCESS_DENIED;
1080 return -1;
1083 /* Open the driver file (Portable Executable format) and determine the
1084 * deriver the cversion. */
1085 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1087 unix_convert(driverpath,conn,NULL,&bad_path,&st);
1089 fsp = open_file_shared(conn, driverpath, &st,
1090 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1091 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1092 0, 0, &access_mode, &action);
1093 if (!fsp) {
1094 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1095 driverpath, errno));
1096 *perr = WERR_ACCESS_DENIED;
1097 goto error_exit;
1099 else {
1100 uint32 major;
1101 uint32 minor;
1102 int ret = get_file_version(fsp, driverpath, &major, &minor);
1103 if (ret == -1) goto error_exit;
1105 if (!ret) {
1106 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1107 goto error_exit;
1111 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1112 * for more details. Version in this case is not just the version of the
1113 * file, but the version in the sense of kernal mode (2) vs. user mode
1114 * (3) drivers. Other bits of the version fields are the version info.
1115 * JRR 010716
1117 cversion = major & 0x0000ffff;
1118 switch (cversion) {
1119 case 2: /* WinNT drivers */
1120 case 3: /* Win2K drivers */
1121 break;
1123 default:
1124 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1125 driverpath, cversion));
1126 goto error_exit;
1129 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1130 driverpath, major, minor));
1133 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1134 driverpath, cversion));
1136 close_file(fsp, True);
1137 close_cnum(conn, user->vuid);
1138 unbecome_user();
1139 *perr = WERR_OK;
1140 return cversion;
1143 error_exit:
1145 if(fsp)
1146 close_file(fsp, True);
1148 close_cnum(conn, user->vuid);
1149 unbecome_user();
1150 return -1;
1153 /****************************************************************************
1154 ****************************************************************************/
1155 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1156 struct current_user *user)
1158 fstring architecture;
1159 fstring new_name;
1160 char *p;
1161 int i;
1162 WERROR err;
1164 /* clean up the driver name.
1165 * we can get .\driver.dll
1166 * or worse c:\windows\system\driver.dll !
1168 /* using an intermediate string to not have overlaping memcpy()'s */
1169 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1170 fstrcpy(new_name, p+1);
1171 fstrcpy(driver->driverpath, new_name);
1174 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1175 fstrcpy(new_name, p+1);
1176 fstrcpy(driver->datafile, new_name);
1179 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1180 fstrcpy(new_name, p+1);
1181 fstrcpy(driver->configfile, new_name);
1184 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1185 fstrcpy(new_name, p+1);
1186 fstrcpy(driver->helpfile, new_name);
1189 if (driver->dependentfiles) {
1190 for (i=0; *driver->dependentfiles[i]; i++) {
1191 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1192 fstrcpy(new_name, p+1);
1193 fstrcpy(driver->dependentfiles[i], new_name);
1198 get_short_archi(architecture, driver->environment);
1200 /* jfm:7/16/2000 the client always sends the cversion=0.
1201 * The server should check which version the driver is by reading
1202 * the PE header of driver->driverpath.
1204 * For Windows 95/98 the version is 0 (so the value sent is correct)
1205 * For Windows NT (the architecture doesn't matter)
1206 * NT 3.1: cversion=0
1207 * NT 3.5/3.51: cversion=1
1208 * NT 4: cversion=2
1209 * NT2K: cversion=3
1211 if ((driver->cversion = get_correct_cversion( architecture,
1212 driver->driverpath, user, &err)) == -1)
1213 return err;
1215 return WERR_OK;
1218 /****************************************************************************
1219 ****************************************************************************/
1220 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
1221 struct current_user *user)
1223 fstring architecture;
1224 fstring new_name;
1225 char *p;
1226 int i;
1227 WERROR err;
1229 /* clean up the driver name.
1230 * we can get .\driver.dll
1231 * or worse c:\windows\system\driver.dll !
1233 /* using an intermediate string to not have overlaping memcpy()'s */
1234 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1235 fstrcpy(new_name, p+1);
1236 fstrcpy(driver->driverpath, new_name);
1239 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1240 fstrcpy(new_name, p+1);
1241 fstrcpy(driver->datafile, new_name);
1244 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1245 fstrcpy(new_name, p+1);
1246 fstrcpy(driver->configfile, new_name);
1249 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1250 fstrcpy(new_name, p+1);
1251 fstrcpy(driver->helpfile, new_name);
1254 if (driver->dependentfiles) {
1255 for (i=0; *driver->dependentfiles[i]; i++) {
1256 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1257 fstrcpy(new_name, p+1);
1258 fstrcpy(driver->dependentfiles[i], new_name);
1263 get_short_archi(architecture, driver->environment);
1265 /* jfm:7/16/2000 the client always sends the cversion=0.
1266 * The server should check which version the driver is by reading
1267 * the PE header of driver->driverpath.
1269 * For Windows 95/98 the version is 0 (so the value sent is correct)
1270 * For Windows NT (the architecture doesn't matter)
1271 * NT 3.1: cversion=0
1272 * NT 3.5/3.51: cversion=1
1273 * NT 4: cversion=2
1274 * NT2K: cversion=3
1276 if ((driver->version = get_correct_cversion(architecture,
1277 driver->driverpath, user, &err)) == -1)
1278 return err;
1280 return WERR_OK;
1283 /****************************************************************************
1284 ****************************************************************************/
1285 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1286 uint32 level, struct current_user *user)
1288 switch (level) {
1289 case 3:
1291 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1292 driver=driver_abstract.info_3;
1293 return clean_up_driver_struct_level_3(driver, user);
1295 case 6:
1297 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1298 driver=driver_abstract.info_6;
1299 return clean_up_driver_struct_level_6(driver, user);
1301 default:
1302 return WERR_INVALID_PARAM;
1306 /****************************************************************************
1307 This function sucks and should be replaced. JRA.
1308 ****************************************************************************/
1310 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1312 dst->cversion = src->version;
1314 fstrcpy( dst->name, src->name);
1315 fstrcpy( dst->environment, src->environment);
1316 fstrcpy( dst->driverpath, src->driverpath);
1317 fstrcpy( dst->datafile, src->datafile);
1318 fstrcpy( dst->configfile, src->configfile);
1319 fstrcpy( dst->helpfile, src->helpfile);
1320 fstrcpy( dst->monitorname, src->monitorname);
1321 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1322 dst->dependentfiles = src->dependentfiles;
1325 #if 0 /* Debugging function */
1327 static char* ffmt(unsigned char *c){
1328 int i;
1329 static char ffmt_str[17];
1331 for (i=0; i<16; i++) {
1332 if ((c[i] < ' ') || (c[i] > '~'))
1333 ffmt_str[i]='.';
1334 else
1335 ffmt_str[i]=c[i];
1337 ffmt_str[16]='\0';
1338 return ffmt_str;
1341 #endif
1343 /****************************************************************************
1344 ****************************************************************************/
1345 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1346 struct current_user *user, WERROR *perr)
1348 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1349 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1350 fstring architecture;
1351 pstring new_dir;
1352 pstring old_name;
1353 pstring new_name;
1354 DATA_BLOB null_pw;
1355 connection_struct *conn;
1356 NTSTATUS nt_status;
1357 pstring inbuf;
1358 pstring outbuf;
1359 int ver = 0;
1360 int i;
1362 memset(inbuf, '\0', sizeof(inbuf));
1363 memset(outbuf, '\0', sizeof(outbuf));
1364 *perr = WERR_OK;
1366 if (level==3)
1367 driver=driver_abstract.info_3;
1368 else if (level==6) {
1369 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1370 driver = &converted_driver;
1371 } else {
1372 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1373 return False;
1376 get_short_archi(architecture, driver->environment);
1379 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1380 * Note we must be root to do this.
1383 become_root();
1384 null_pw = data_blob(NULL, 0);
1385 conn = make_connection_with_chdir("print$", null_pw, "A:", user->vuid, &nt_status);
1386 unbecome_root();
1388 if (conn == NULL) {
1389 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1390 *perr = ntstatus_to_werror(nt_status);
1391 return False;
1395 * Save who we are - we are temporarily becoming the connection user.
1398 if (!become_user(conn, conn->vuid)) {
1399 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1400 return False;
1404 * make the directories version and version\driver_name
1405 * under the architecture directory.
1407 DEBUG(5,("Creating first directory\n"));
1408 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1409 mkdir_internal(conn, new_dir);
1411 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1412 * listed for this driver which has already been moved, skip it (note:
1413 * drivers may list the same file name several times. Then check if the
1414 * file already exists in archi\cversion\, if so, check that the version
1415 * info (or time stamps if version info is unavailable) is newer (or the
1416 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1417 * Otherwise, delete the file.
1419 * If a file is not moved to archi\cversion\ because of an error, all the
1420 * rest of the 'unmoved' driver files are removed from archi\. If one or
1421 * more of the driver's files was already moved to archi\cversion\, it
1422 * potentially leaves the driver in a partially updated state. Version
1423 * trauma will most likely occur if an client attempts to use any printer
1424 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1425 * done is appropriate... later JRR
1428 DEBUG(5,("Moving files now !\n"));
1430 if (driver->driverpath && strlen(driver->driverpath)) {
1431 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1432 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1433 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1434 NTSTATUS status;
1435 status = rename_internals(conn, new_name, old_name, True);
1436 if (!NT_STATUS_IS_OK(status)) {
1437 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1438 new_name, old_name));
1439 *perr = ntstatus_to_werror(status);
1440 unlink_internals(conn, 0, new_name);
1441 ver = -1;
1444 else
1445 unlink_internals(conn, 0, new_name);
1448 if (driver->datafile && strlen(driver->datafile)) {
1449 if (!strequal(driver->datafile, driver->driverpath)) {
1450 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1451 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1452 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1453 NTSTATUS status;
1454 status = rename_internals(conn, new_name, old_name, True);
1455 if (!NT_STATUS_IS_OK(status)) {
1456 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1457 new_name, old_name));
1458 *perr = ntstatus_to_werror(status);
1459 unlink_internals(conn, 0, new_name);
1460 ver = -1;
1463 else
1464 unlink_internals(conn, 0, new_name);
1468 if (driver->configfile && strlen(driver->configfile)) {
1469 if (!strequal(driver->configfile, driver->driverpath) &&
1470 !strequal(driver->configfile, driver->datafile)) {
1471 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1472 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1473 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1474 NTSTATUS status;
1475 status = rename_internals(conn, new_name, old_name, True);
1476 if (!NT_STATUS_IS_OK(status)) {
1477 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1478 new_name, old_name));
1479 *perr = ntstatus_to_werror(status);
1480 unlink_internals(conn, 0, new_name);
1481 ver = -1;
1484 else
1485 unlink_internals(conn, 0, new_name);
1489 if (driver->helpfile && strlen(driver->helpfile)) {
1490 if (!strequal(driver->helpfile, driver->driverpath) &&
1491 !strequal(driver->helpfile, driver->datafile) &&
1492 !strequal(driver->helpfile, driver->configfile)) {
1493 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1494 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1495 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1496 NTSTATUS status;
1497 status = rename_internals(conn, new_name, old_name, True);
1498 if (!NT_STATUS_IS_OK(status)) {
1499 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1500 new_name, old_name));
1501 *perr = ntstatus_to_werror(status);
1502 unlink_internals(conn, 0, new_name);
1503 ver = -1;
1506 else
1507 unlink_internals(conn, 0, new_name);
1511 if (driver->dependentfiles) {
1512 for (i=0; *driver->dependentfiles[i]; i++) {
1513 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1514 !strequal(driver->dependentfiles[i], driver->datafile) &&
1515 !strequal(driver->dependentfiles[i], driver->configfile) &&
1516 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1517 int j;
1518 for (j=0; j < i; j++) {
1519 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1520 goto NextDriver;
1524 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1525 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
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);
1540 NextDriver: ;
1544 close_cnum(conn, user->vuid);
1545 unbecome_user();
1547 return ver == -1 ? False : True;
1550 /****************************************************************************
1551 ****************************************************************************/
1552 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1554 int len, buflen;
1555 fstring architecture;
1556 pstring directory;
1557 pstring temp_name;
1558 pstring key;
1559 char *buf;
1560 int i, ret;
1561 TDB_DATA kbuf, dbuf;
1563 get_short_archi(architecture, driver->environment);
1565 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1566 * \\server is added in the rpc server layer.
1567 * It does make sense to NOT store the server's name in the printer TDB.
1570 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1572 /* .inf files do not always list a file for each of the four standard files.
1573 * Don't prepend a path to a null filename, or client claims:
1574 * "The server on which the printer resides does not have a suitable
1575 * <printer driver name> printer driver installed. Click OK if you
1576 * wish to install the driver on your local machine."
1578 if (strlen(driver->driverpath)) {
1579 fstrcpy(temp_name, driver->driverpath);
1580 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1583 if (strlen(driver->datafile)) {
1584 fstrcpy(temp_name, driver->datafile);
1585 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1588 if (strlen(driver->configfile)) {
1589 fstrcpy(temp_name, driver->configfile);
1590 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1593 if (strlen(driver->helpfile)) {
1594 fstrcpy(temp_name, driver->helpfile);
1595 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1598 if (driver->dependentfiles) {
1599 for (i=0; *driver->dependentfiles[i]; i++) {
1600 fstrcpy(temp_name, driver->dependentfiles[i]);
1601 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1605 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1607 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1609 buf = NULL;
1610 len = buflen = 0;
1612 again:
1613 len = 0;
1614 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1615 driver->cversion,
1616 driver->name,
1617 driver->environment,
1618 driver->driverpath,
1619 driver->datafile,
1620 driver->configfile,
1621 driver->helpfile,
1622 driver->monitorname,
1623 driver->defaultdatatype);
1625 if (driver->dependentfiles) {
1626 for (i=0; *driver->dependentfiles[i]; i++) {
1627 len += tdb_pack(buf+len, buflen-len, "f",
1628 driver->dependentfiles[i]);
1632 if (len != buflen) {
1633 char *tb;
1635 tb = (char *)Realloc(buf, len);
1636 if (!tb) {
1637 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1638 ret = -1;
1639 goto done;
1641 else buf = tb;
1642 buflen = len;
1643 goto again;
1647 kbuf.dptr = key;
1648 kbuf.dsize = strlen(key)+1;
1649 dbuf.dptr = buf;
1650 dbuf.dsize = len;
1652 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1654 done:
1655 if (ret)
1656 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1658 SAFE_FREE(buf);
1659 return ret;
1662 /****************************************************************************
1663 ****************************************************************************/
1664 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1666 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1668 ZERO_STRUCT(info3);
1669 info3.cversion = driver->version;
1670 fstrcpy(info3.name,driver->name);
1671 fstrcpy(info3.environment,driver->environment);
1672 fstrcpy(info3.driverpath,driver->driverpath);
1673 fstrcpy(info3.datafile,driver->datafile);
1674 fstrcpy(info3.configfile,driver->configfile);
1675 fstrcpy(info3.helpfile,driver->helpfile);
1676 fstrcpy(info3.monitorname,driver->monitorname);
1677 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1678 info3.dependentfiles = driver->dependentfiles;
1680 return add_a_printer_driver_3(&info3);
1684 /****************************************************************************
1685 ****************************************************************************/
1686 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring driver, fstring arch)
1688 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1690 ZERO_STRUCT(info);
1692 fstrcpy(info.name, driver);
1693 fstrcpy(info.defaultdatatype, "RAW");
1695 fstrcpy(info.driverpath, "");
1696 fstrcpy(info.datafile, "");
1697 fstrcpy(info.configfile, "");
1698 fstrcpy(info.helpfile, "");
1700 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1701 return WERR_NOMEM;
1703 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1704 fstrcpy(info.dependentfiles[0], "");
1706 *info_ptr = memdup(&info, sizeof(info));
1708 return WERR_OK;
1711 /****************************************************************************
1712 ****************************************************************************/
1713 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, fstring arch, uint32 version)
1715 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1716 TDB_DATA kbuf, dbuf;
1717 fstring architecture;
1718 int len = 0;
1719 int i;
1720 pstring key;
1722 ZERO_STRUCT(driver);
1724 get_short_archi(architecture, arch);
1726 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1728 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1730 kbuf.dptr = key;
1731 kbuf.dsize = strlen(key)+1;
1733 dbuf = tdb_fetch(tdb_drivers, kbuf);
1734 if (!dbuf.dptr)
1735 return WERR_ACCESS_DENIED;
1737 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1738 &driver.cversion,
1739 driver.name,
1740 driver.environment,
1741 driver.driverpath,
1742 driver.datafile,
1743 driver.configfile,
1744 driver.helpfile,
1745 driver.monitorname,
1746 driver.defaultdatatype);
1748 i=0;
1749 while (len < dbuf.dsize) {
1750 fstring *tddfs;
1752 tddfs = (fstring *)Realloc(driver.dependentfiles,
1753 sizeof(fstring)*(i+2));
1754 if (tddfs == NULL) {
1755 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1756 break;
1758 else driver.dependentfiles = tddfs;
1760 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1761 &driver.dependentfiles[i]);
1762 i++;
1764 if (driver.dependentfiles != NULL)
1765 fstrcpy(driver.dependentfiles[i], "");
1767 SAFE_FREE(dbuf.dptr);
1769 if (len != dbuf.dsize) {
1770 SAFE_FREE(driver.dependentfiles);
1772 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1775 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1777 return WERR_OK;
1780 /****************************************************************************
1781 ****************************************************************************/
1782 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1784 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1785 TDB_DATA kbuf;
1786 pstring key;
1787 int i;
1788 line[0] = '\0';
1790 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1791 DEBUG(10,("driver key: [%s]\n", key));
1793 kbuf.dptr = key;
1794 kbuf.dsize = strlen(key)+1;
1795 if (!tdb_exists(tdb_drivers, kbuf))
1796 return False;
1798 ZERO_STRUCT(info3);
1799 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1801 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1802 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1803 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1804 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1805 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1806 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1807 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1809 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1810 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1811 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1813 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1814 trim_string(info3->driverpath, "\\print$\\WIN40\\0\\", 0);
1815 pstrcat(line, info3->driverpath);
1816 pstrcat(line, ":");
1817 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1818 pstrcat(line, info3->datafile);
1819 pstrcat(line, ":");
1820 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1821 pstrcat(line, info3->helpfile);
1822 pstrcat(line, ":");
1823 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1824 pstrcat(line, info3->monitorname);
1825 pstrcat(line, ":");
1826 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1827 pstrcat(line, ":");
1829 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1830 if (i)
1831 pstrcat(line, ","); /* don't end in a "," */
1832 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1833 pstrcat(line, info3->dependentfiles[i]);
1836 SAFE_FREE(info3);
1838 return True;
1841 /****************************************************************************
1842 Debugging function, dump at level 6 the struct in the logs.
1843 ****************************************************************************/
1845 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1847 uint32 result;
1848 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1849 int i;
1851 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1853 switch (level)
1855 case 3:
1857 if (driver.info_3 == NULL)
1858 result=5;
1859 else {
1860 info3=driver.info_3;
1862 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1863 DEBUGADD(106,("name:[%s]\n", info3->name));
1864 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1865 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1866 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1867 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1868 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1869 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1870 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1872 for (i=0; info3->dependentfiles &&
1873 *info3->dependentfiles[i]; i++) {
1874 DEBUGADD(106,("dependentfile:[%s]\n",
1875 info3->dependentfiles[i]));
1877 result=0;
1879 break;
1881 default:
1882 DEBUGADD(106,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1883 result=1;
1884 break;
1887 return result;
1890 /****************************************************************************
1891 ****************************************************************************/
1892 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1894 int len = 0;
1896 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1898 if (!nt_devmode) return len;
1900 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1901 nt_devmode->devicename,
1902 nt_devmode->formname,
1904 nt_devmode->specversion,
1905 nt_devmode->driverversion,
1906 nt_devmode->size,
1907 nt_devmode->driverextra,
1908 nt_devmode->orientation,
1909 nt_devmode->papersize,
1910 nt_devmode->paperlength,
1911 nt_devmode->paperwidth,
1912 nt_devmode->scale,
1913 nt_devmode->copies,
1914 nt_devmode->defaultsource,
1915 nt_devmode->printquality,
1916 nt_devmode->color,
1917 nt_devmode->duplex,
1918 nt_devmode->yresolution,
1919 nt_devmode->ttoption,
1920 nt_devmode->collate,
1921 nt_devmode->logpixels,
1923 nt_devmode->fields,
1924 nt_devmode->bitsperpel,
1925 nt_devmode->pelswidth,
1926 nt_devmode->pelsheight,
1927 nt_devmode->displayflags,
1928 nt_devmode->displayfrequency,
1929 nt_devmode->icmmethod,
1930 nt_devmode->icmintent,
1931 nt_devmode->mediatype,
1932 nt_devmode->dithertype,
1933 nt_devmode->reserved1,
1934 nt_devmode->reserved2,
1935 nt_devmode->panningwidth,
1936 nt_devmode->panningheight,
1937 nt_devmode->private);
1940 if (nt_devmode->private) {
1941 len += tdb_pack(buf+len, buflen-len, "B",
1942 nt_devmode->driverextra,
1943 nt_devmode->private);
1946 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1948 return len;
1951 /****************************************************************************
1952 ****************************************************************************/
1953 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1955 int len = 0;
1957 while (param != NULL) {
1958 len += tdb_pack(buf+len, buflen-len, "pfdB",
1959 param,
1960 param->value,
1961 param->type,
1962 param->data_len,
1963 param->data);
1964 param=param->next;
1967 len += tdb_pack(buf+len, buflen-len, "p", param);
1969 return len;
1973 /****************************************************************************
1974 Delete a printer - this just deletes the printer info file, any open
1975 handles are not affected.
1976 ****************************************************************************/
1978 uint32 del_a_printer(char *sharename)
1980 pstring key;
1981 TDB_DATA kbuf;
1983 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1985 kbuf.dptr=key;
1986 kbuf.dsize=strlen(key)+1;
1988 tdb_delete(tdb_printers, kbuf);
1989 return 0;
1992 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
1993 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1994 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1995 /****************************************************************************
1996 ****************************************************************************/
1997 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1999 pstring key;
2000 char *buf;
2001 int buflen, len;
2002 WERROR ret;
2003 TDB_DATA kbuf, dbuf;
2006 * in addprinter: no servername and the printer is the name
2007 * in setprinter: servername is \\server
2008 * and printer is \\server\\printer
2010 * Samba manages only local printers.
2011 * we currently don't support things like path=\\other_server\printer
2014 if (info->servername[0]!='\0') {
2015 trim_string(info->printername, info->servername, NULL);
2016 trim_string(info->printername, "\\", NULL);
2017 info->servername[0]='\0';
2021 * JFM: one day I'll forget.
2022 * below that's info->portname because that's the SAMBA sharename
2023 * and I made NT 'thinks' it's the portname
2024 * the info->sharename is the thing you can name when you add a printer
2025 * that's the short-name when you create shared printer for 95/98
2026 * So I've made a limitation in SAMBA: you can only have 1 printer model
2027 * behind a SAMBA share.
2030 buf = NULL;
2031 buflen = 0;
2033 again:
2034 len = 0;
2035 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2036 info->attributes,
2037 info->priority,
2038 info->default_priority,
2039 info->starttime,
2040 info->untiltime,
2041 info->status,
2042 info->cjobs,
2043 info->averageppm,
2044 info->changeid,
2045 info->c_setprinter,
2046 info->setuptime,
2047 info->servername,
2048 info->printername,
2049 info->sharename,
2050 info->portname,
2051 info->drivername,
2052 info->comment,
2053 info->location,
2054 info->sepfile,
2055 info->printprocessor,
2056 info->datatype,
2057 info->parameters);
2059 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2061 len += pack_specifics(info->specific, buf+len, buflen-len);
2063 if (buflen != len) {
2064 char *tb;
2066 tb = (char *)Realloc(buf, len);
2067 if (!tb) {
2068 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2069 ret = WERR_NOMEM;
2070 goto done;
2072 else buf = tb;
2073 buflen = len;
2074 goto again;
2078 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2080 kbuf.dptr = key;
2081 kbuf.dsize = strlen(key)+1;
2082 dbuf.dptr = buf;
2083 dbuf.dsize = len;
2085 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2087 done:
2088 if (!W_ERROR_IS_OK(ret))
2089 DEBUG(8, ("error updating printer to tdb on disk\n"));
2091 SAFE_FREE(buf);
2093 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2094 info->sharename, info->drivername, info->portname, len));
2096 return ret;
2100 /****************************************************************************
2101 ****************************************************************************/
2102 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
2104 NT_PRINTER_PARAM *current;
2106 DEBUG(108,("add_a_specific_param\n"));
2108 (*param)->next=NULL;
2110 if (info_2->specific == NULL)
2112 info_2->specific=*param;
2114 else
2116 current=info_2->specific;
2117 while (current->next != NULL) {
2118 current=current->next;
2120 current->next=*param;
2123 *param = NULL;
2126 /****************************************************************************
2127 ****************************************************************************/
2128 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
2130 NT_PRINTER_PARAM *current;
2131 NT_PRINTER_PARAM *previous;
2133 current=info_2->specific;
2134 previous=current;
2136 if (current==NULL) return (False);
2138 if ( !strcmp(current->value, param->value) &&
2139 (strlen(current->value)==strlen(param->value)) ) {
2140 DEBUG(109,("deleting first value\n"));
2141 info_2->specific=current->next;
2142 SAFE_FREE(current->data);
2143 SAFE_FREE(current);
2144 DEBUG(109,("deleted first value\n"));
2145 return (True);
2148 current=previous->next;
2150 while ( current!=NULL ) {
2151 if (!strcmp(current->value, param->value) &&
2152 strlen(current->value)==strlen(param->value) ) {
2153 DEBUG(109,("deleting current value\n"));
2154 previous->next=current->next;
2155 SAFE_FREE(current->data);
2156 SAFE_FREE(current);
2157 DEBUG(109,("deleted current value\n"));
2158 return(True);
2161 previous=previous->next;
2162 current=current->next;
2164 return (False);
2167 /****************************************************************************
2168 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2169 ****************************************************************************/
2170 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2172 NT_PRINTER_PARAM *param = *param_ptr;
2174 if(param == NULL)
2175 return;
2177 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2179 SAFE_FREE(param->data);
2180 SAFE_FREE(*param_ptr);
2183 /****************************************************************************
2184 Malloc and return an NT devicemode.
2185 ****************************************************************************/
2187 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2190 char adevice[32];
2191 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2193 if (nt_devmode == NULL) {
2194 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2195 return NULL;
2198 ZERO_STRUCTP(nt_devmode);
2200 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2201 fstrcpy(nt_devmode->devicename, adevice);
2203 fstrcpy(nt_devmode->formname, "Letter");
2205 nt_devmode->specversion = 0x0401;
2206 nt_devmode->driverversion = 0x0400;
2207 nt_devmode->size = 0x00DC;
2208 nt_devmode->driverextra = 0x0000;
2209 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2210 DEFAULTSOURCE | COPIES | SCALE |
2211 PAPERSIZE | ORIENTATION;
2212 nt_devmode->orientation = 1;
2213 nt_devmode->papersize = PAPER_LETTER;
2214 nt_devmode->paperlength = 0;
2215 nt_devmode->paperwidth = 0;
2216 nt_devmode->scale = 0x64;
2217 nt_devmode->copies = 1;
2218 nt_devmode->defaultsource = BIN_FORMSOURCE;
2219 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2220 nt_devmode->color = COLOR_MONOCHROME;
2221 nt_devmode->duplex = DUP_SIMPLEX;
2222 nt_devmode->yresolution = 0;
2223 nt_devmode->ttoption = TT_SUBDEV;
2224 nt_devmode->collate = COLLATE_FALSE;
2225 nt_devmode->icmmethod = 0;
2226 nt_devmode->icmintent = 0;
2227 nt_devmode->mediatype = 0;
2228 nt_devmode->dithertype = 0;
2230 /* non utilisés par un driver d'imprimante */
2231 nt_devmode->logpixels = 0;
2232 nt_devmode->bitsperpel = 0;
2233 nt_devmode->pelswidth = 0;
2234 nt_devmode->pelsheight = 0;
2235 nt_devmode->displayflags = 0;
2236 nt_devmode->displayfrequency = 0;
2237 nt_devmode->reserved1 = 0;
2238 nt_devmode->reserved2 = 0;
2239 nt_devmode->panningwidth = 0;
2240 nt_devmode->panningheight = 0;
2242 nt_devmode->private = NULL;
2243 return nt_devmode;
2246 /****************************************************************************
2247 Deepcopy an NT devicemode.
2248 ****************************************************************************/
2250 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2252 NT_DEVICEMODE *new_nt_devicemode = NULL;
2254 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2255 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2256 return NULL;
2259 new_nt_devicemode->private = NULL;
2260 if (nt_devicemode->private != NULL) {
2261 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2262 SAFE_FREE(new_nt_devicemode);
2263 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2264 return NULL;
2268 return new_nt_devicemode;
2271 /****************************************************************************
2272 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2273 ****************************************************************************/
2275 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2277 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2279 if(nt_devmode == NULL)
2280 return;
2282 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2284 SAFE_FREE(nt_devmode->private);
2285 SAFE_FREE(*devmode_ptr);
2288 /****************************************************************************
2289 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2290 ****************************************************************************/
2291 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2293 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2294 NT_PRINTER_PARAM *param_ptr;
2296 if(info == NULL)
2297 return;
2299 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2301 free_nt_devicemode(&info->devmode);
2303 for(param_ptr = info->specific; param_ptr; ) {
2304 NT_PRINTER_PARAM *tofree = param_ptr;
2306 param_ptr = param_ptr->next;
2307 free_nt_printer_param(&tofree);
2310 SAFE_FREE(*info_ptr);
2314 /****************************************************************************
2315 ****************************************************************************/
2316 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2318 int len = 0;
2319 int extra_len = 0;
2320 NT_DEVICEMODE devmode;
2322 ZERO_STRUCT(devmode);
2324 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2326 if (!*nt_devmode) return len;
2328 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2329 devmode.devicename,
2330 devmode.formname,
2332 &devmode.specversion,
2333 &devmode.driverversion,
2334 &devmode.size,
2335 &devmode.driverextra,
2336 &devmode.orientation,
2337 &devmode.papersize,
2338 &devmode.paperlength,
2339 &devmode.paperwidth,
2340 &devmode.scale,
2341 &devmode.copies,
2342 &devmode.defaultsource,
2343 &devmode.printquality,
2344 &devmode.color,
2345 &devmode.duplex,
2346 &devmode.yresolution,
2347 &devmode.ttoption,
2348 &devmode.collate,
2349 &devmode.logpixels,
2351 &devmode.fields,
2352 &devmode.bitsperpel,
2353 &devmode.pelswidth,
2354 &devmode.pelsheight,
2355 &devmode.displayflags,
2356 &devmode.displayfrequency,
2357 &devmode.icmmethod,
2358 &devmode.icmintent,
2359 &devmode.mediatype,
2360 &devmode.dithertype,
2361 &devmode.reserved1,
2362 &devmode.reserved2,
2363 &devmode.panningwidth,
2364 &devmode.panningheight,
2365 &devmode.private);
2367 if (devmode.private) {
2368 /* the len in tdb_unpack is an int value and
2369 * devmode.driverextra is only a short
2371 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2372 devmode.driverextra=(uint16)extra_len;
2374 /* check to catch an invalid TDB entry so we don't segfault */
2375 if (devmode.driverextra == 0) {
2376 devmode.private = NULL;
2380 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2382 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2383 if (devmode.private)
2384 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2386 return len;
2389 /****************************************************************************
2390 ****************************************************************************/
2391 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2393 int len = 0;
2394 NT_PRINTER_PARAM param, *p;
2396 *list = NULL;
2398 while (1) {
2399 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2400 if (!p) break;
2402 len += tdb_unpack(buf+len, buflen-len, "fdB",
2403 param.value,
2404 &param.type,
2405 &param.data_len,
2406 &param.data);
2407 param.next = *list;
2408 *list = memdup(&param, sizeof(param));
2410 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2413 return len;
2416 static void map_to_os2_driver(fstring drivername)
2418 static BOOL initialised=False;
2419 static fstring last_from,last_to;
2420 char *mapfile = lp_os2_driver_map();
2421 char **lines = NULL;
2422 int numlines = 0;
2423 int i;
2425 if (!strlen(drivername))
2426 return;
2428 if (!*mapfile)
2429 return;
2431 if (!initialised) {
2432 *last_from = *last_to = 0;
2433 initialised = True;
2436 if (strequal(drivername,last_from)) {
2437 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2438 fstrcpy(drivername,last_to);
2439 return;
2442 lines = file_lines_load(mapfile, &numlines);
2443 if (numlines == 0) {
2444 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2445 return;
2448 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2450 for( i = 0; i < numlines; i++) {
2451 char *nt_name = lines[i];
2452 char *os2_name = strchr(nt_name,'=');
2454 if (!os2_name)
2455 continue;
2457 *os2_name++ = 0;
2459 while (isspace(*nt_name))
2460 nt_name++;
2462 if (!*nt_name || strchr("#;",*nt_name))
2463 continue;
2466 int l = strlen(nt_name);
2467 while (l && isspace(nt_name[l-1])) {
2468 nt_name[l-1] = 0;
2469 l--;
2473 while (isspace(*os2_name))
2474 os2_name++;
2477 int l = strlen(os2_name);
2478 while (l && isspace(os2_name[l-1])) {
2479 os2_name[l-1] = 0;
2480 l--;
2484 if (strequal(nt_name,drivername)) {
2485 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2486 fstrcpy(last_from,drivername);
2487 fstrcpy(last_to,os2_name);
2488 fstrcpy(drivername,os2_name);
2489 file_lines_free(lines);
2490 return;
2494 file_lines_free(lines);
2497 /****************************************************************************
2498 get a default printer info 2 struct
2499 ****************************************************************************/
2500 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2502 int snum;
2503 NT_PRINTER_INFO_LEVEL_2 info;
2505 ZERO_STRUCT(info);
2507 snum = lp_servicenumber(sharename);
2509 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2510 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2511 get_called_name(), sharename);
2512 fstrcpy(info.sharename, sharename);
2513 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2514 fstrcpy(info.drivername, lp_printerdriver(snum));
2516 /* by setting the driver name to an empty string, a local NT admin
2517 can now run the **local** APW to install a local printer driver
2518 for a Samba shared printer in 2.2. Without this, drivers **must** be
2519 installed on the Samba server for NT clients --jerry */
2520 #if 0 /* JERRY --do not uncomment-- */
2521 if (!*info.drivername)
2522 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2523 #endif
2526 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2528 pstrcpy(info.comment, "");
2529 fstrcpy(info.printprocessor, "winprint");
2530 fstrcpy(info.datatype, "RAW");
2532 info.attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK; /* attributes */
2534 info.starttime = 0; /* Minutes since 12:00am GMT */
2535 info.untiltime = 0; /* Minutes since 12:00am GMT */
2536 info.priority = 1;
2537 info.default_priority = 1;
2538 info.setuptime = (uint32)time(NULL);
2541 * I changed this as I think it is better to have a generic
2542 * DEVMODE than to crash Win2k explorer.exe --jerry
2543 * See the HP Deskjet 990c Win2k drivers for an example.
2545 * However the default devmode appears to cause problems
2546 * with the HP CLJ 8500 PCL driver. Hence the addition of
2547 * the "default devmode" parameter --jerry 22/01/2002
2550 if (lp_default_devmode(snum)) {
2551 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2552 goto fail;
2554 else {
2555 info.devmode = NULL;
2558 /* This will get the current RPC talloc context, but we should be
2559 passing this as a parameter... fixme... JRA ! */
2561 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2562 goto fail;
2564 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2565 if (! *info_ptr) {
2566 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2567 goto fail;
2570 return WERR_OK;
2572 fail:
2573 if (info.devmode)
2574 free_nt_devicemode(&info.devmode);
2575 return WERR_ACCESS_DENIED;
2578 /****************************************************************************
2579 ****************************************************************************/
2580 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2582 pstring key;
2583 NT_PRINTER_INFO_LEVEL_2 info;
2584 int len = 0;
2585 TDB_DATA kbuf, dbuf;
2586 fstring printername;
2588 ZERO_STRUCT(info);
2590 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2592 kbuf.dptr = key;
2593 kbuf.dsize = strlen(key)+1;
2595 dbuf = tdb_fetch(tdb_printers, kbuf);
2596 if (!dbuf.dptr)
2597 return get_a_printer_2_default(info_ptr, sharename);
2599 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2600 &info.attributes,
2601 &info.priority,
2602 &info.default_priority,
2603 &info.starttime,
2604 &info.untiltime,
2605 &info.status,
2606 &info.cjobs,
2607 &info.averageppm,
2608 &info.changeid,
2609 &info.c_setprinter,
2610 &info.setuptime,
2611 info.servername,
2612 info.printername,
2613 info.sharename,
2614 info.portname,
2615 info.drivername,
2616 info.comment,
2617 info.location,
2618 info.sepfile,
2619 info.printprocessor,
2620 info.datatype,
2621 info.parameters);
2623 /* Samba has to have shared raw drivers. */
2624 info.attributes |= (PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK);
2626 /* Restore the stripped strings. */
2627 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2628 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
2629 info.printername);
2630 fstrcpy(info.printername, printername);
2632 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2635 * Some client drivers freak out if there is a NULL devmode
2636 * (probably the driver is not checking before accessing
2637 * the devmode pointer) --jerry
2639 * See comments in get_a_printer_2_default()
2642 if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode)
2644 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
2645 printername));
2646 info.devmode = construct_nt_devicemode(printername);
2649 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2651 /* This will get the current RPC talloc context, but we should be
2652 passing this as a parameter... fixme... JRA ! */
2654 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2656 /* Fix for OS/2 drivers. */
2658 if (get_remote_arch() == RA_OS2)
2659 map_to_os2_driver(info.drivername);
2661 SAFE_FREE(dbuf.dptr);
2662 *info_ptr=memdup(&info, sizeof(info));
2664 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2665 sharename, info.printername, info.drivername));
2667 return WERR_OK;
2670 /****************************************************************************
2671 debugging function, dump at level 6 the struct in the logs
2672 ****************************************************************************/
2673 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2675 uint32 result;
2676 NT_PRINTER_INFO_LEVEL_2 *info2;
2678 DEBUG(106,("Dumping printer at level [%d]\n", level));
2680 switch (level)
2682 case 2:
2684 if (printer.info_2 == NULL)
2685 result=5;
2686 else
2688 info2=printer.info_2;
2690 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2691 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2692 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2693 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2694 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2695 DEBUGADD(106,("status:[%d]\n", info2->status));
2696 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2697 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2698 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2699 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2700 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2702 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2703 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2704 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2705 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2706 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2707 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2708 DEBUGADD(106,("location:[%s]\n", info2->location));
2709 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2710 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2711 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2712 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2713 result=0;
2715 break;
2717 default:
2718 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
2719 result=1;
2720 break;
2723 return result;
2726 /****************************************************************************
2727 Get the parameters we can substitute in an NT print job.
2728 ****************************************************************************/
2730 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2732 NT_PRINTER_INFO_LEVEL *printer = NULL;
2734 **printername = **sharename = **portname = '\0';
2736 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2737 return;
2739 fstrcpy(*printername, printer->info_2->printername);
2740 fstrcpy(*sharename, printer->info_2->sharename);
2741 fstrcpy(*portname, printer->info_2->portname);
2743 free_a_printer(&printer, 2);
2746 /****************************************************************************
2747 Update the changeid time.
2748 This is SO NASTY as some drivers need this to change, others need it
2749 static. This value will change every second, and I must hope that this
2750 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
2751 UTAH ! JRA.
2752 ****************************************************************************/
2754 static uint32 rev_changeid(void)
2756 struct timeval tv;
2758 get_process_uptime(&tv);
2760 #if 1 /* JERRY */
2761 /* Return changeid as msec since spooler restart */
2762 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
2763 #else
2765 * This setting seems to work well but is too untested
2766 * to replace the above calculation. Left in for experiementation
2767 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
2769 return tv.tv_sec * 10 + tv.tv_usec / 100000;
2770 #endif
2774 * The function below are the high level ones.
2775 * only those ones must be called from the spoolss code.
2776 * JFM.
2779 /****************************************************************************
2780 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2781 ****************************************************************************/
2783 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2785 WERROR result;
2787 dump_a_printer(printer, level);
2789 switch (level)
2791 case 2:
2794 * Update the changestamp. Emperical tests show that the
2795 * ChangeID is always updated,but c_setprinter is
2796 * global spooler variable (not per printer).
2799 /* ChangeID **must** be increasing over the lifetime
2800 of client's spoolss service in order for the
2801 client's cache to show updates */
2803 printer.info_2->changeid = rev_changeid();
2806 * Because one day someone will ask:
2807 * NT->NT An admin connection to a remote
2808 * printer show changes imeediately in
2809 * the properities dialog
2811 * A non-admin connection will only show the
2812 * changes after viewing the properites page
2813 * 2 times. Seems to be related to a
2814 * race condition in the client between the spooler
2815 * updating the local cache and the Explorer.exe GUI
2816 * actually displaying the properties.
2818 * This is fixed in Win2k. admin/non-admin
2819 * connections both display changes immediately.
2821 * 14/12/01 --jerry
2824 result=update_a_printer_2(printer.info_2);
2825 break;
2827 default:
2828 result=WERR_UNKNOWN_LEVEL;
2829 break;
2832 return result;
2835 /****************************************************************************
2836 Initialize printer devmode & data with previously saved driver init values.
2837 ****************************************************************************/
2839 static BOOL set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
2841 int len = 0;
2842 pstring key;
2843 TDB_DATA kbuf, dbuf;
2844 NT_PRINTER_PARAM *current;
2845 NT_PRINTER_INFO_LEVEL_2 info;
2848 * Delete any printer data 'specifics' already set. When called for driver
2849 * replace, there will generally be some, but during an add printer, there
2850 * should not be any (if there are delete them).
2852 while ( (current=info_ptr->specific) != NULL ) {
2853 info_ptr->specific=current->next;
2854 SAFE_FREE(current->data);
2855 SAFE_FREE(current);
2858 ZERO_STRUCT(info);
2860 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
2862 kbuf.dptr = key;
2863 kbuf.dsize = strlen(key)+1;
2865 dbuf = tdb_fetch(tdb_drivers, kbuf);
2866 if (!dbuf.dptr) {
2868 * When changing to a driver that has no init info in the tdb, remove
2869 * the previous drivers init info and leave the new on blank.
2871 free_nt_devicemode(&info_ptr->devmode);
2872 return False;
2876 * Get the saved DEVMODE..
2878 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2881 * The saved DEVMODE contains the devicename from the printer used during
2882 * the initialization save. Change it to reflect the new printer.
2884 ZERO_STRUCT(info.devmode->devicename);
2885 fstrcpy(info.devmode->devicename, info_ptr->printername);
2889 * NT/2k does not change out the entire DeviceMode of a printer
2890 * when changing the driver. Only the driverextra, private, &
2891 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
2893 * Later e4xamination revealed that Windows NT/2k does reset the
2894 * the printer's device mode, bit **only** when you change a
2895 * property of the device mode such as the page orientation.
2896 * --jerry
2899 #if 1 /* JERRY */
2902 * Bind the saved DEVMODE to the new the printer.
2904 free_nt_devicemode(&info_ptr->devmode);
2905 info_ptr->devmode = info.devmode;
2906 #else
2907 /* copy the entire devmode if we currently don't have one */
2909 if (!info_ptr->devmode) {
2910 DEBUG(10,("set_driver_init_2: Current Devmode is NULL. Copying entire Device Mode\n"));
2911 info_ptr->devmode = info.devmode;
2913 else {
2914 /* only set the necessary fields */
2916 DEBUG(10,("set_driver_init_2: Setting driverversion [0x%x] and private data [0x%x]\n",
2917 info.devmode->driverversion, info.devmode->driverextra));
2919 info_ptr->devmode->driverversion = info.devmode->driverversion;
2921 SAFE_FREE(info_ptr->devmode->private);
2922 info_ptr->devmode->private = NULL;
2924 if (info.devmode->driverversion)
2925 info_ptr->devmode->private = memdup(info.devmode->private, info.devmode->driverversion);
2927 free_nt_devicemode(&info.devmode);
2929 #endif
2931 DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
2932 info_ptr->printername, info_ptr->drivername));
2935 * Add the printer data 'specifics' to the new printer
2937 len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len);
2939 SAFE_FREE(dbuf.dptr);
2941 return True;
2944 /****************************************************************************
2945 Initialize printer devmode & data with previously saved driver init values.
2946 When a printer is created using AddPrinter, the drivername bound to the
2947 printer is used to lookup previously saved driver initialization info, which
2948 is bound to the new printer.
2949 ****************************************************************************/
2951 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
2953 BOOL result = False;
2955 switch (level)
2957 case 2:
2958 result=set_driver_init_2(printer->info_2);
2959 break;
2961 default:
2962 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
2963 level));
2964 break;
2967 return result;
2970 /****************************************************************************
2971 Delete driver init data stored for a specified driver
2972 ****************************************************************************/
2974 BOOL del_driver_init(char *drivername)
2976 pstring key;
2977 TDB_DATA kbuf;
2979 if (!drivername || !*drivername) {
2980 DEBUG(3,("del_driver_init: No drivername specified!\n"));
2981 return False;
2984 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
2986 kbuf.dptr = key;
2987 kbuf.dsize = strlen(key)+1;
2989 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
2991 return (tdb_delete(tdb_drivers, kbuf) == 0);
2994 /****************************************************************************
2995 Pack up the DEVMODE and specifics for a printer into a 'driver init' entry
2996 in the tdb. Note: this is different from the driver entry and the printer
2997 entry. There should be a single driver init entry for each driver regardless
2998 of whether it was installed from NT or 2K. Technically, they should be
2999 different, but they work out to the same struct.
3000 ****************************************************************************/
3002 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3004 pstring key;
3005 char *buf;
3006 int buflen, len, ret;
3007 TDB_DATA kbuf, dbuf;
3009 buf = NULL;
3010 buflen = 0;
3012 again:
3013 len = 0;
3014 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3016 len += pack_specifics(info->specific, buf+len, buflen-len);
3018 if (buflen != len) {
3019 char *tb;
3021 tb = (char *)Realloc(buf, len);
3022 if (!tb) {
3023 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3024 ret = -1;
3025 goto done;
3027 else buf = tb;
3028 buflen = len;
3029 goto again;
3032 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3034 kbuf.dptr = key;
3035 kbuf.dsize = strlen(key)+1;
3036 dbuf.dptr = buf;
3037 dbuf.dsize = len;
3039 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3041 done:
3042 if (ret == -1)
3043 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3045 SAFE_FREE(buf);
3047 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n",
3048 info->sharename, info->drivername));
3050 return ret;
3053 /****************************************************************************
3054 Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer
3055 ****************************************************************************/
3057 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3059 uint32 result;
3061 dump_a_printer(printer, level);
3063 switch (level)
3065 case 2:
3067 result=update_driver_init_2(printer.info_2);
3068 break;
3070 default:
3071 result=1;
3072 break;
3075 return result;
3078 /****************************************************************************
3079 Convert the printer data value, a REG_BINARY array, into an initialization
3080 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3081 got to keep the endians happy :).
3082 ****************************************************************************/
3084 static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode)
3086 BOOL result = False;
3087 prs_struct ps;
3088 DEVICEMODE devmode;
3090 ZERO_STRUCT(devmode);
3092 prs_init(&ps, 0, ctx, UNMARSHALL);
3093 ps.data_p = (char *)param->data;
3094 ps.buffer_size = param->data_len;
3096 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3097 result = convert_devicemode("", &devmode, &nt_devmode);
3098 else
3099 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3101 return result;
3104 /****************************************************************************
3105 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3107 1. Use the driver's config DLL to this UNC printername and:
3108 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3109 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3110 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3112 The last step triggers saving the "driver initialization" information for
3113 this printer into the tdb. Later, new printers that use this driver will
3114 have this initialization information bound to them. This simulates the
3115 driver initialization, as if it had run on the Samba server (as it would
3116 have done on NT).
3118 The Win32 client side code requirement sucks! But until we can run arbitrary
3119 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3121 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3122 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3123 about it and you will realize why. JRR 010720
3124 ****************************************************************************/
3126 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
3128 WERROR status = WERR_OK;
3129 TALLOC_CTX *ctx = NULL;
3130 NT_DEVICEMODE *nt_devmode = NULL;
3131 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3134 * When the DEVMODE is already set on the printer, don't try to unpack it.
3137 if (!printer->info_2->devmode && param->data_len) {
3139 * Set devmode on printer info, so entire printer initialization can be
3140 * saved to tdb.
3143 if ((ctx = talloc_init()) == NULL)
3144 return WERR_NOMEM;
3146 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3147 status = WERR_NOMEM;
3148 goto done;
3151 ZERO_STRUCTP(nt_devmode);
3154 * The DEVMODE is held in the 'data' component of the param in raw binary.
3155 * Convert it to to a devmode structure
3157 if (!convert_driver_init(param, ctx, nt_devmode)) {
3158 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3159 status = WERR_INVALID_PARAM;
3160 goto done;
3163 printer->info_2->devmode = nt_devmode;
3167 * Pack up and add (or update) the DEVMODE and any current printer data to
3168 * a 'driver init' element in the tdb
3172 if (update_driver_init(*printer, 2)!=0) {
3173 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3174 status = WERR_NOMEM;
3175 goto done;
3179 * If driver initialization info was successfully saved, set the current
3180 * printer to match it. This allows initialization of the current printer
3181 * as well as the driver.
3183 status = mod_a_printer(*printer, 2);
3184 if (!W_ERROR_IS_OK(status)) {
3185 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3186 printer->info_2->printername));
3189 #if 0 /* JERRY */
3190 srv_spoolss_sendnotify(p, handle);
3191 #endif
3193 done:
3194 talloc_destroy(ctx);
3195 if (nt_devmode)
3196 SAFE_FREE(nt_devmode->private);
3197 SAFE_FREE(nt_devmode);
3198 printer->info_2->devmode = tmp_devmode;
3200 return status;
3203 /****************************************************************************
3204 Update the driver init info (DEVMODE and specifics) for a printer
3205 ****************************************************************************/
3207 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
3209 WERROR status = WERR_OK;
3211 switch (level)
3213 case 2:
3215 status=save_driver_init_2(printer, param);
3216 break;
3218 default:
3219 status=WERR_UNKNOWN_LEVEL;
3220 break;
3223 return status;
3226 /****************************************************************************
3227 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3228 ****************************************************************************/
3230 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
3232 WERROR result;
3233 NT_PRINTER_INFO_LEVEL *printer = NULL;
3235 *pp_printer = NULL;
3237 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3239 switch (level)
3241 case 2:
3243 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3244 DEBUG(0,("get_a_printer: malloc fail.\n"));
3245 return WERR_NOMEM;
3247 ZERO_STRUCTP(printer);
3248 result=get_a_printer_2(&printer->info_2, sharename);
3249 if (W_ERROR_IS_OK(result)) {
3250 dump_a_printer(*printer, level);
3251 *pp_printer = printer;
3252 } else {
3253 SAFE_FREE(printer);
3255 break;
3257 default:
3258 result=WERR_UNKNOWN_LEVEL;
3259 break;
3262 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
3264 return result;
3267 /****************************************************************************
3268 Deletes a NT_PRINTER_INFO_LEVEL struct.
3269 ****************************************************************************/
3271 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3273 uint32 result;
3274 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3276 DEBUG(104,("freeing a printer at level [%d]\n", level));
3278 if (printer == NULL)
3279 return 0;
3281 switch (level)
3283 case 2:
3285 if (printer->info_2 != NULL)
3287 free_nt_printer_info_level_2(&printer->info_2);
3288 result=0;
3290 else
3292 result=4;
3294 break;
3296 default:
3297 result=1;
3298 break;
3301 SAFE_FREE(*pp_printer);
3302 return result;
3305 /****************************************************************************
3306 ****************************************************************************/
3307 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3309 uint32 result;
3310 DEBUG(104,("adding a printer at level [%d]\n", level));
3311 dump_a_printer_driver(driver, level);
3313 switch (level)
3315 case 3:
3317 result=add_a_printer_driver_3(driver.info_3);
3318 break;
3321 case 6:
3323 result=add_a_printer_driver_6(driver.info_6);
3324 break;
3326 default:
3327 result=1;
3328 break;
3331 return result;
3333 /****************************************************************************
3334 ****************************************************************************/
3335 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3336 fstring drivername, fstring architecture, uint32 version)
3338 WERROR result;
3340 switch (level)
3342 case 3:
3343 /* Sometime we just want any version of the driver */
3345 if ( version == DRIVER_ANY_VERSION ) {
3346 /* look for Win2k first and then for NT4 */
3347 result = get_a_printer_driver_3(&driver->info_3, drivername,
3348 architecture, 3);
3350 if ( !W_ERROR_IS_OK(result) ) {
3351 result = get_a_printer_driver_3( &driver->info_3,
3352 drivername, architecture, 2 );
3355 else {
3356 result = get_a_printer_driver_3(&driver->info_3, drivername,
3357 architecture, version);
3359 break;
3361 default:
3362 result=W_ERROR(1);
3363 break;
3366 if (W_ERROR_IS_OK(result))
3367 dump_a_printer_driver(*driver, level);
3369 return result;
3372 /****************************************************************************
3373 ****************************************************************************/
3374 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3376 uint32 result;
3378 switch (level)
3380 case 3:
3382 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3383 if (driver.info_3 != NULL)
3385 info3=driver.info_3;
3386 SAFE_FREE(info3->dependentfiles);
3387 ZERO_STRUCTP(info3);
3388 SAFE_FREE(info3);
3389 result=0;
3391 else
3393 result=4;
3395 break;
3397 case 6:
3399 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3400 if (driver.info_6 != NULL)
3402 info6=driver.info_6;
3403 SAFE_FREE(info6->dependentfiles);
3404 SAFE_FREE(info6->previousnames);
3405 ZERO_STRUCTP(info6);
3406 SAFE_FREE(info6);
3407 result=0;
3409 else
3411 result=4;
3413 break;
3415 default:
3416 result=1;
3417 break;
3419 return result;
3423 /****************************************************************************
3424 Determine whether or not a particular driver is currently assigned
3425 to a printer
3426 ****************************************************************************/
3428 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i )
3430 int snum;
3431 int n_services = lp_numservices();
3432 NT_PRINTER_INFO_LEVEL *printer = NULL;
3434 if ( !i )
3435 return False;
3437 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
3439 /* loop through the printers.tdb and check for the drivername */
3441 for (snum=0; snum<n_services; snum++)
3443 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
3444 continue;
3446 if ( !W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) )
3447 continue;
3449 if ( !StrCaseCmp(i->name, printer->info_2->drivername) ) {
3450 free_a_printer( &printer, 2 );
3451 return True;
3454 free_a_printer( &printer, 2 );
3457 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
3459 /* report that the driver is not in use by default */
3461 return False;
3465 /**********************************************************************
3466 Check to see if a ogiven file is in use by *info
3467 *********************************************************************/
3469 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
3471 char *s;
3473 if ( !info )
3474 return False;
3476 if ( strequal(file, info->driverpath) )
3477 return True;
3479 if ( strequal(file, info->datafile) )
3480 return True;
3482 if ( strequal(file, info->configfile) )
3483 return True;
3485 if ( strequal(file, info->helpfile) )
3486 return True;
3488 s = (char*) info->dependentfiles;
3490 if ( s ) {
3491 while ( *s )
3493 if ( strequal(file, s) )
3494 return True;
3495 s += strlen(s) + 1;
3499 return False;
3503 /**********************************************************************
3504 Utility function to remove the dependent file pointed to by the
3505 input parameter from the list
3506 *********************************************************************/
3508 static void trim_dependent_file( char* s )
3510 char *p;
3512 /* set p to the next character string in the list */
3514 p = s + strlen( s ) + 1;
3516 /* check to see that we have another string to copy back */
3518 if ( *p == '\0' )
3520 /* loop over s copying characters from p to s */
3521 while ( *p!='\0' && *(p+1)!='\0' )
3522 *s++ = *p++;
3525 /* add the two trailing NULL's */
3527 *s = '\0';
3528 *(s+1) = '\0';
3531 /**********************************************************************
3532 Check if any of the files used by src are also used by drv
3533 *********************************************************************/
3535 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
3536 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
3538 BOOL in_use = False;
3539 char *s;
3541 if ( !src || !drv )
3542 return False;
3544 /* check each file. Remove it from the src structure if it overlaps */
3546 if ( drv_file_in_use(src->driverpath, drv) ) {
3547 in_use = True;
3548 fstrcpy( src->driverpath, "" );
3551 if ( drv_file_in_use(src->datafile, drv) ) {
3552 in_use = True;
3553 fstrcpy( src->datafile, "" );
3556 if ( drv_file_in_use(src->configfile, drv) ) {
3557 in_use = True;
3558 fstrcpy( src->configfile, "" );
3561 s = (char*)src->dependentfiles;
3563 if ( s ) {
3564 while ( *s )
3566 if ( drv_file_in_use(s, drv) ) {
3567 in_use = True;
3568 trim_dependent_file( s );
3570 else
3571 s += strlen(s) + 1;
3576 return in_use;
3579 /****************************************************************************
3580 Determine whether or not a particular driver files are currently being
3581 used by any other driver.
3583 Return value is True if any files were in use by other drivers
3584 and False otherwise.
3586 Upon return, *info has been modified to only contain the driver files
3587 which are not in use
3588 ****************************************************************************/
3590 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
3592 int i;
3593 int ndrivers;
3594 uint32 version;
3595 fstring *list = NULL;
3596 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3598 /* loop over all driver versions */
3600 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
3602 for ( version=0; version<DRIVER_MAX_VERSION; version++ )
3604 /* get the list of drivers */
3606 list = NULL;
3607 ndrivers = get_ntdrivers(&list, info->environment, version);
3609 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
3610 ndrivers, info->environment, version));
3612 if (ndrivers == -1)
3613 continue;
3615 /* check each driver for overlap in files */
3617 for (i=0; i<ndrivers; i++)
3619 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
3621 ZERO_STRUCT(driver);
3623 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i],
3624 info->environment, version)) )
3626 SAFE_FREE(list);
3627 return True;
3630 /* check if d2 uses any files from d1 */
3631 /* only if this is a different driver than the one being deleted */
3633 if ( !strequal(info->name, driver.info_3->name)
3634 || (info->cversion != driver.info_3->cversion) )
3636 if ( trim_overlap_drv_files(info, driver.info_3) ) {
3637 free_a_printer_driver(driver, 3);
3638 SAFE_FREE( list );
3639 return True;
3643 free_a_printer_driver(driver, 3);
3646 SAFE_FREE(list);
3649 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
3651 return False;
3654 /****************************************************************************
3655 Actually delete the driver files. Make sure that
3656 printer_driver_files_in_use() return False before calling
3657 this.
3658 ****************************************************************************/
3660 static NTSTATUS delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i )
3662 char *s;
3664 if ( !i )
3665 return NT_STATUS_ACCESS_DENIED;
3667 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", i->name, i->cversion));
3670 if ( *i->driverpath )
3671 DEBUG(10,("deleting [%s]\n", i->driverpath));
3672 if ( *i->configfile )
3673 DEBUG(10,("deleting [%s]\n", i->configfile));
3674 if ( *i->datafile )
3675 DEBUG(10,("deleting [%s]\n", i->datafile));
3676 if ( *i->helpfile )
3677 DEBUG(10,("deleting [%s]\n", i->helpfile));
3679 s = (char*)i->dependentfiles;
3681 if ( s ) {
3682 while ( *s ) {
3683 DEBUG(10,("deleting dependent file [%s]\n", s));
3684 s += strlen( s ) + 1;
3688 return NT_STATUS_OK;
3691 /****************************************************************************
3692 Remove a printer driver from the TDB. This assumes that the the driver was
3693 previously looked up.
3694 ***************************************************************************/
3695 WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, BOOL delete_files)
3697 pstring key;
3698 fstring arch;
3699 TDB_DATA kbuf;
3701 /* delete the tdb data first */
3703 get_short_archi(arch, i->environment);
3704 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
3705 arch, i->cversion, i->name);
3707 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
3708 key, delete_files ? "TRUE" : "FALSE" ));
3710 kbuf.dptr=key;
3711 kbuf.dsize=strlen(key)+1;
3713 if (tdb_delete(tdb_drivers, kbuf) == -1) {
3714 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
3715 return WERR_ACCESS_DENIED;
3719 * now delete any associated files if delete_files == True
3720 * even if this part failes, we return succes because the
3721 * driver doesn not exist any more
3724 if ( delete_files )
3725 delete_driver_files( i );
3727 DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
3728 i->name));
3730 return WERR_OK;
3732 /****************************************************************************
3733 ****************************************************************************/
3734 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
3735 fstring value, uint8 **data, uint32 *type, uint32 *len)
3737 /* right now that's enough ! */
3738 NT_PRINTER_PARAM *param;
3739 int i=0;
3741 param=printer.info_2->specific;
3743 while (param != NULL && i < param_index) {
3744 param=param->next;
3745 i++;
3748 if (param == NULL)
3749 return False;
3751 /* exited because it exist */
3752 *type=param->type;
3753 StrnCpy(value, param->value, sizeof(fstring)-1);
3754 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3755 if(*data == NULL)
3756 return False;
3757 ZERO_STRUCTP(*data);
3758 memcpy(*data, param->data, param->data_len);
3759 *len=param->data_len;
3760 return True;
3763 /****************************************************************************
3764 ****************************************************************************/
3765 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
3766 fstring value, uint8 **data, uint32 *type, uint32 *len)
3768 /* right now that's enough ! */
3769 NT_PRINTER_PARAM *param;
3771 DEBUG(10, ("get_specific_param\n"));
3773 param=printer.info_2->specific;
3775 while (param != NULL)
3777 #if 1 /* JRA - I think this should be case insensitive.... */
3778 if ( strequal(value, param->value)
3779 #else
3780 if ( !strcmp(value, param->value)
3781 #endif
3782 && strlen(value)==strlen(param->value))
3783 break;
3785 param=param->next;
3788 if (param != NULL)
3790 DEBUGADD(10, ("get_specific_param: found one param\n"));
3791 /* exited because it exist */
3792 *type=param->type;
3794 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3795 if(*data == NULL)
3796 return False;
3797 memcpy(*data, param->data, param->data_len);
3798 *len=param->data_len;
3800 DEBUGADD(10, ("get_specific_param: exit true\n"));
3801 return (True);
3803 DEBUGADD(10, ("get_specific_param: exit false\n"));
3804 return (False);
3807 /****************************************************************************
3808 Store a security desc for a printer.
3809 ****************************************************************************/
3811 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
3813 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3814 SEC_DESC_BUF *old_secdesc_ctr = NULL;
3815 prs_struct ps;
3816 TALLOC_CTX *mem_ctx = NULL;
3817 fstring key;
3818 WERROR status;
3820 mem_ctx = talloc_init();
3821 if (mem_ctx == NULL)
3822 return WERR_NOMEM;
3824 /* The old owner and group sids of the security descriptor are not
3825 present when new ACEs are added or removed by changing printer
3826 permissions through NT. If they are NULL in the new security
3827 descriptor then copy them over from the old one. */
3829 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3830 DOM_SID *owner_sid, *group_sid;
3831 SEC_ACL *dacl, *sacl;
3832 SEC_DESC *psd = NULL;
3833 size_t size;
3835 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3837 /* Pick out correct owner and group sids */
3839 owner_sid = secdesc_ctr->sec->owner_sid ?
3840 secdesc_ctr->sec->owner_sid :
3841 old_secdesc_ctr->sec->owner_sid;
3843 group_sid = secdesc_ctr->sec->grp_sid ?
3844 secdesc_ctr->sec->grp_sid :
3845 old_secdesc_ctr->sec->grp_sid;
3847 dacl = secdesc_ctr->sec->dacl ?
3848 secdesc_ctr->sec->dacl :
3849 old_secdesc_ctr->sec->dacl;
3851 sacl = secdesc_ctr->sec->sacl ?
3852 secdesc_ctr->sec->sacl :
3853 old_secdesc_ctr->sec->sacl;
3855 /* Make a deep copy of the security descriptor */
3857 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3858 owner_sid, group_sid,
3859 sacl,
3860 dacl,
3861 &size);
3863 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3866 if (!new_secdesc_ctr) {
3867 new_secdesc_ctr = secdesc_ctr;
3870 /* Store the security descriptor in a tdb */
3872 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3873 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3875 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3876 &ps, 1)) {
3877 status = WERR_BADFUNC;
3878 goto out;
3881 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3883 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
3884 status = WERR_OK;
3885 } else {
3886 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3887 status = WERR_BADFUNC;
3890 /* Free malloc'ed memory */
3892 out:
3894 prs_mem_free(&ps);
3895 if (mem_ctx)
3896 talloc_destroy(mem_ctx);
3897 return status;
3900 /****************************************************************************
3901 Construct a default security descriptor buffer for a printer.
3902 ****************************************************************************/
3904 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3906 SEC_ACE ace[3];
3907 SEC_ACCESS sa;
3908 SEC_ACL *psa = NULL;
3909 SEC_DESC_BUF *sdb = NULL;
3910 SEC_DESC *psd = NULL;
3911 DOM_SID owner_sid;
3912 size_t sd_size;
3914 /* Create an ACE where Everyone is allowed to print */
3916 init_sec_access(&sa, PRINTER_ACE_PRINT);
3917 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3918 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3920 /* Make the security descriptor owned by the Administrators group
3921 on the PDC of the domain. */
3923 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
3924 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3925 } else {
3927 /* Backup plan - make printer owned by admins.
3928 This should emulate a lanman printer as security
3929 settings can't be changed. */
3931 sid_copy(&owner_sid, get_global_sam_sid());
3932 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3935 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3936 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3937 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
3938 SEC_ACE_FLAG_INHERIT_ONLY);
3940 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3941 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3942 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3944 /* The ACL revision number in rpc_secdesc.h differs from the one
3945 created by NT when setting ACE entries in printer
3946 descriptors. NT4 complains about the property being edited by a
3947 NT5 machine. */
3949 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
3950 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
3951 &owner_sid, NULL,
3952 NULL, psa, &sd_size);
3955 if (!psd) {
3956 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
3957 return NULL;
3960 sdb = make_sec_desc_buf(ctx, sd_size, psd);
3962 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
3963 (unsigned int)sd_size));
3965 return sdb;
3968 /****************************************************************************
3969 Get a security desc for a printer.
3970 ****************************************************************************/
3972 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
3974 prs_struct ps;
3975 fstring key;
3976 char *temp;
3978 if ((temp = strchr(printername + 2, '\\'))) {
3979 printername = temp + 1;
3982 /* Fetch security descriptor from tdb */
3984 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3986 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
3987 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
3989 DEBUG(4,("using default secdesc for %s\n", printername));
3991 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
3992 return False;
3995 /* Save default security descriptor for later */
3997 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
3998 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4000 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4001 tdb_prs_store(tdb_printers, key, &ps);
4003 prs_mem_free(&ps);
4005 return True;
4008 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4009 this security descriptor has been created when winbindd was
4010 down. Take ownership of security descriptor. */
4012 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4013 DOM_SID owner_sid;
4015 /* Change sd owner to workgroup administrator */
4017 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4018 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4019 SEC_DESC *psd = NULL;
4020 size_t size;
4022 /* Create new sd */
4024 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4026 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
4027 &owner_sid,
4028 (*secdesc_ctr)->sec->grp_sid,
4029 (*secdesc_ctr)->sec->sacl,
4030 (*secdesc_ctr)->sec->dacl,
4031 &size);
4033 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4035 /* Swap with other one */
4037 *secdesc_ctr = new_secdesc_ctr;
4039 /* Set it */
4041 nt_printing_setsec(printername, *secdesc_ctr);
4045 if (DEBUGLEVEL >= 10) {
4046 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4047 int i;
4049 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4050 printername, the_acl->num_aces));
4052 for (i = 0; i < the_acl->num_aces; i++) {
4053 fstring sid_str;
4055 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4057 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4058 the_acl->ace[i].type, the_acl->ace[i].flags,
4059 the_acl->ace[i].info.mask));
4063 prs_mem_free(&ps);
4064 return True;
4067 /* error code:
4068 0: everything OK
4069 1: level not implemented
4070 2: file doesn't exist
4071 3: can't allocate memory
4072 4: can't free memory
4073 5: non existant struct
4077 A printer and a printer driver are 2 different things.
4078 NT manages them separatelly, Samba does the same.
4079 Why ? Simply because it's easier and it makes sense !
4081 Now explanation: You have 3 printers behind your samba server,
4082 2 of them are the same make and model (laser A and B). But laser B
4083 has an 3000 sheet feeder and laser A doesn't such an option.
4084 Your third printer is an old dot-matrix model for the accounting :-).
4086 If the /usr/local/samba/lib directory (default dir), you will have
4087 5 files to describe all of this.
4089 3 files for the printers (1 by printer):
4090 NTprinter_laser A
4091 NTprinter_laser B
4092 NTprinter_accounting
4093 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4094 NTdriver_printer model X
4095 NTdriver_printer model Y
4097 jfm: I should use this comment for the text file to explain
4098 same thing for the forms BTW.
4099 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4103 /* Convert generic access rights to printer object specific access rights.
4104 It turns out that NT4 security descriptors use generic access rights and
4105 NT5 the object specific ones. */
4107 void map_printer_permissions(SEC_DESC *sd)
4109 int i;
4111 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4112 se_map_generic(&sd->dacl->ace[i].info.mask,
4113 &printer_generic_mapping);
4117 /****************************************************************************
4118 Check a user has permissions to perform the given operation. We use the
4119 permission constants defined in include/rpc_spoolss.h to check the various
4120 actions we perform when checking printer access.
4122 PRINTER_ACCESS_ADMINISTER:
4123 print_queue_pause, print_queue_resume, update_printer_sec,
4124 update_printer, spoolss_addprinterex_level_2,
4125 _spoolss_setprinterdata
4127 PRINTER_ACCESS_USE:
4128 print_job_start
4130 JOB_ACCESS_ADMINISTER:
4131 print_job_delete, print_job_pause, print_job_resume,
4132 print_queue_purge
4134 ****************************************************************************/
4135 BOOL print_access_check(struct current_user *user, int snum, int access_type)
4137 SEC_DESC_BUF *secdesc = NULL;
4138 uint32 access_granted;
4139 NTSTATUS status;
4140 BOOL result;
4141 const char *pname;
4142 TALLOC_CTX *mem_ctx = NULL;
4143 extern struct current_user current_user;
4145 /* If user is NULL then use the current_user structure */
4147 if (!user)
4148 user = &current_user;
4150 /* Always allow root or printer admins to do anything */
4152 if (user->uid == 0 ||
4153 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
4154 return True;
4157 /* Get printer name */
4159 pname = PRINTERNAME(snum);
4161 if (!pname || !*pname) {
4162 errno = EACCES;
4163 return False;
4166 /* Get printer security descriptor */
4168 if(!(mem_ctx = talloc_init())) {
4169 errno = ENOMEM;
4170 return False;
4173 nt_printing_getsec(mem_ctx, pname, &secdesc);
4175 if (access_type == JOB_ACCESS_ADMINISTER) {
4176 SEC_DESC_BUF *parent_secdesc = secdesc;
4178 /* Create a child security descriptor to check permissions
4179 against. This is because print jobs are child objects
4180 objects of a printer. */
4182 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4184 /* Now this is the bit that really confuses me. The access
4185 type needs to be changed from JOB_ACCESS_ADMINISTER to
4186 PRINTER_ACCESS_ADMINISTER for this to work. Something
4187 to do with the child (job) object becoming like a
4188 printer?? -tpot */
4190 access_type = PRINTER_ACCESS_ADMINISTER;
4193 /* Check access */
4195 map_printer_permissions(secdesc->sec);
4197 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4198 &access_granted, &status);
4200 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4202 talloc_destroy(mem_ctx);
4204 if (!result)
4205 errno = EACCES;
4207 return result;
4210 /****************************************************************************
4211 Check the time parameters allow a print operation.
4212 *****************************************************************************/
4214 BOOL print_time_access_check(int snum)
4216 NT_PRINTER_INFO_LEVEL *printer = NULL;
4217 BOOL ok = False;
4218 time_t now = time(NULL);
4219 struct tm *t;
4220 uint32 mins;
4222 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4223 return False;
4225 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
4226 ok = True;
4228 t = gmtime(&now);
4229 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4231 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
4232 ok = True;
4234 free_a_printer(&printer, 2);
4236 if (!ok)
4237 errno = EACCES;
4239 return ok;
4242 #if 0 /* JERRY - not used */
4243 /****************************************************************************
4244 Attempt to write a default device.
4245 *****************************************************************************/
4247 WERROR printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
4249 NT_PRINTER_INFO_LEVEL *printer = NULL;
4250 WERROR result;
4253 * Don't bother if no default devicemode was sent.
4256 if (printer_default->devmode_cont.devmode == NULL)
4257 return WERR_OK;
4259 result = get_a_printer(&printer, 2, lp_servicename(snum));
4260 if (!W_ERROR_IS_OK(result)) return result;
4263 * Just ignore it if we already have a devmode.
4265 #if 0
4266 if (printer->info_2->devmode != NULL)
4267 goto done;
4268 #endif
4270 * We don't have a devicemode and we're trying to write
4271 * one. Check we have the access needed.
4273 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
4275 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
4276 PRINTER_ACCESS_ADMINISTER) {
4277 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
4278 result = WERR_ACCESS_DENIED;
4279 goto done;
4282 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4283 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
4284 lp_servicename(snum) ));
4285 result = WERR_ACCESS_DENIED;
4286 /*result = NT_STATUS_NO_PROBLEMO;*/
4287 goto done;
4290 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
4293 * Convert the on the wire devicemode format to the internal one.
4296 if (!convert_devicemode(printer->info_2->printername,
4297 printer_default->devmode_cont.devmode,
4298 &printer->info_2->devmode)) {
4299 result = WERR_NOMEM;
4300 goto done;
4304 * Finally write back to the tdb.
4307 result = mod_a_printer(*printer, 2);
4309 done:
4311 free_a_printer(&printer, 2);
4312 return result;
4314 #endif /* JERRY */