r585: merge of fix for KB828741 -- pw chg -- from 3.0
[Samba.git] / source / printing / nt_printing.c
blob52a7386010c76b377bedbd4c5020f9d52769e129
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 const 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,0);
291 int32 vers_id;
293 /* Cope with byte-reversed older versions of the db. */
294 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
295 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
296 /* Written on a bigendian machine with old fetch_int code. Save as le. */
297 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
298 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
299 vers_id = NTDRIVERS_DATABASE_VERSION;
302 if (vers_id != NTDRIVERS_DATABASE_VERSION) {
304 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
305 if (!upgrade_to_version_3())
306 return False;
307 } else
308 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
310 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
313 tdb_unlock_bystring(tdb_drivers, vstring);
315 update_c_setprinter(True);
318 * register callback to handle updating printers as new
319 * drivers are installed
321 message_register(MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer);
323 return True;
326 /*******************************************************************
327 tdb traversal function for counting printers.
328 ********************************************************************/
330 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
331 TDB_DATA data, void *context)
333 int *printer_count = (int*)context;
335 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
336 (*printer_count)++;
337 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
340 return 0;
343 /*******************************************************************
344 Update the spooler global c_setprinter. This variable is initialized
345 when the parent smbd starts with the number of existing printers. It
346 is monotonically increased by the current number of printers *after*
347 each add or delete printer RPC. Only Microsoft knows why... JRR020119
348 ********************************************************************/
350 uint32 update_c_setprinter(BOOL initialize)
352 int32 c_setprinter;
353 int32 printer_count = 0;
355 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER,0);
357 /* Traverse the tdb, counting the printers */
358 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
360 /* If initializing, set c_setprinter to current printers count
361 * otherwise, bump it by the current printer count
363 if (!initialize)
364 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
365 else
366 c_setprinter = printer_count;
368 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
369 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
371 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
373 return (uint32)c_setprinter;
376 /*******************************************************************
377 Get the spooler global c_setprinter, accounting for initialization.
378 ********************************************************************/
380 uint32 get_c_setprinter(void)
382 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
384 if (c_setprinter == (int32)-1)
385 c_setprinter = update_c_setprinter(True);
387 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
389 return (uint32)c_setprinter;
392 /****************************************************************************
393 Get builtin form struct list.
394 ****************************************************************************/
396 int get_builtin_ntforms(nt_forms_struct **list)
398 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
399 return sizeof(default_forms) / sizeof(default_forms[0]);
402 /****************************************************************************
403 get a builtin form struct
404 ****************************************************************************/
406 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
408 int i,count;
409 fstring form_name;
410 unistr2_to_dos(form_name, uni_formname, sizeof(form_name)-1);
411 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
412 count = sizeof(default_forms) / sizeof(default_forms[0]);
413 for (i=0;i<count;i++) {
414 if (strequal(form_name,default_forms[i].name)) {
415 DEBUGADD(6,("Found builtin form %s \n", form_name));
416 memcpy(form,&default_forms[i],sizeof(*form));
417 break;
421 return (i !=count);
424 /****************************************************************************
425 get a form struct list
426 ****************************************************************************/
427 int get_ntforms(nt_forms_struct **list)
429 TDB_DATA kbuf, newkey, dbuf;
430 nt_forms_struct *tl;
431 nt_forms_struct form;
432 int ret;
433 int i;
434 int n = 0;
436 for (kbuf = tdb_firstkey(tdb_forms);
437 kbuf.dptr;
438 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
439 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
441 dbuf = tdb_fetch(tdb_forms, kbuf);
442 if (!dbuf.dptr) continue;
444 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
445 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
446 &i, &form.flag, &form.width, &form.length, &form.left,
447 &form.top, &form.right, &form.bottom);
448 SAFE_FREE(dbuf.dptr);
449 if (ret != dbuf.dsize) continue;
451 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
452 if (!tl) {
453 DEBUG(0,("get_ntforms: Realloc fail.\n"));
454 return 0;
456 *list = tl;
457 (*list)[n] = form;
458 n++;
462 return n;
465 /****************************************************************************
466 write a form struct list
467 ****************************************************************************/
468 int write_ntforms(nt_forms_struct **list, int number)
470 pstring buf, key;
471 int len;
472 TDB_DATA kbuf,dbuf;
473 int i;
475 for (i=0;i<number;i++) {
476 /* save index, so list is rebuilt in correct order */
477 len = tdb_pack(buf, sizeof(buf), "dddddddd",
478 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
479 (*list)[i].left, (*list)[i].top, (*list)[i].right,
480 (*list)[i].bottom);
481 if (len > sizeof(buf)) break;
482 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
483 dos_to_unix(key); /* Convert key to unix-codepage */
484 kbuf.dsize = strlen(key)+1;
485 kbuf.dptr = key;
486 dbuf.dsize = len;
487 dbuf.dptr = buf;
488 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
491 return i;
494 /****************************************************************************
495 add a form struct at the end of the list
496 ****************************************************************************/
497 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
499 int n=0;
500 BOOL update;
501 fstring form_name;
502 nt_forms_struct *tl;
505 * NT tries to add forms even when
506 * they are already in the base
507 * only update the values if already present
510 update=False;
512 unistr2_to_dos(form_name, &form->name, sizeof(form_name)-1);
513 for (n=0; n<*count; n++) {
514 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
515 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
516 update=True;
517 break;
521 if (update==False) {
522 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
523 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
524 return False;
526 *list = tl;
527 unistr2_to_dos((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
528 (*count)++;
531 (*list)[n].flag=form->flags;
532 (*list)[n].width=form->size_x;
533 (*list)[n].length=form->size_y;
534 (*list)[n].left=form->left;
535 (*list)[n].top=form->top;
536 (*list)[n].right=form->right;
537 (*list)[n].bottom=form->bottom;
539 return True;
542 /****************************************************************************
543 delete a named form struct
544 ****************************************************************************/
545 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
547 pstring key;
548 TDB_DATA kbuf;
549 int n=0;
550 fstring form_name;
552 *ret = WERR_OK;
554 unistr2_to_dos(form_name, del_name, sizeof(form_name)-1);
556 for (n=0; n<*count; n++) {
557 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
558 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
559 break;
563 if (n == *count) {
564 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
565 *ret = WERR_INVALID_PARAM;
566 return False;
569 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
570 dos_to_unix(key); /* Convert key to unix-codepage */
571 kbuf.dsize = strlen(key)+1;
572 kbuf.dptr = key;
573 if (tdb_delete(tdb_forms, kbuf) != 0) {
574 *ret = WERR_NOMEM;
575 return False;
578 return True;
581 /****************************************************************************
582 update a form struct
583 ****************************************************************************/
584 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
586 int n=0;
587 fstring form_name;
588 unistr2_to_dos(form_name, &(form->name), sizeof(form_name)-1);
590 DEBUG(106, ("[%s]\n", form_name));
591 for (n=0; n<count; n++)
593 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
594 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
595 break;
598 if (n==count) return;
600 (*list)[n].flag=form->flags;
601 (*list)[n].width=form->size_x;
602 (*list)[n].length=form->size_y;
603 (*list)[n].left=form->left;
604 (*list)[n].top=form->top;
605 (*list)[n].right=form->right;
606 (*list)[n].bottom=form->bottom;
609 /****************************************************************************
610 get the nt drivers list
612 traverse the database and look-up the matching names
613 ****************************************************************************/
614 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
616 int total=0;
617 fstring short_archi;
618 fstring *fl;
619 pstring key;
620 TDB_DATA kbuf, newkey;
622 get_short_archi(short_archi, architecture);
623 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
625 for (kbuf = tdb_firstkey(tdb_drivers);
626 kbuf.dptr;
627 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
628 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
630 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
631 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
632 return -1;
634 else *list = fl;
636 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
637 total++;
640 return(total);
643 /****************************************************************************
644 function to do the mapping between the long architecture name and
645 the short one.
646 ****************************************************************************/
648 BOOL get_short_archi(char *short_archi, const char *long_archi)
650 struct table {
651 const char *long_archi;
652 const char *short_archi;
655 struct table archi_table[]=
657 {"Windows 4.0", "WIN40" },
658 {"Windows NT x86", "W32X86" },
659 {"Windows NT R4000", "W32MIPS" },
660 {"Windows NT Alpha_AXP", "W32ALPHA" },
661 {"Windows NT PowerPC", "W32PPC" },
662 {NULL, "" }
665 int i=-1;
667 DEBUG(107,("Getting architecture dependant directory\n"));
669 if (long_archi == NULL) {
670 DEBUGADD(107,("Bad long_archi param.!\n"));
671 return False;
674 do {
675 i++;
676 } while ( (archi_table[i].long_archi!=NULL ) &&
677 StrCaseCmp(long_archi, archi_table[i].long_archi) );
679 if (archi_table[i].long_archi==NULL) {
680 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
681 return False;
684 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
686 DEBUGADD(108,("index: [%d]\n", i));
687 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
688 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
690 return True;
693 /****************************************************************************
694 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
695 There are two case to be covered here: PE (Portable Executable) and NE (New
696 Executable) files. Both files support the same INFO structure, but PE files
697 store the signature in unicode, and NE files store it as !unicode.
698 returns -1 on error, 1 on version info found, and 0 on no version info found.
699 ****************************************************************************/
701 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
703 int i;
704 char *buf;
705 ssize_t byte_count;
707 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
708 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
709 fname, PE_HEADER_SIZE));
710 goto error_exit;
713 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
714 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
715 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
716 fname, byte_count));
717 goto no_version_info;
720 /* Is this really a DOS header? */
721 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
722 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
723 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
724 goto no_version_info;
727 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
728 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
729 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
730 fname, errno));
731 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
732 goto no_version_info;
735 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
736 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
737 fname, byte_count));
738 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
739 goto no_version_info;
742 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
743 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
744 int num_sections;
745 int section_table_bytes;
747 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
748 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
749 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
750 /* At this point, we assume the file is in error. It still could be somthing
751 * else besides a PE file, but it unlikely at this point.
753 goto error_exit;
756 /* get the section table */
757 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
758 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
759 SAFE_FREE(buf);
760 if ((buf=malloc(section_table_bytes)) == NULL) {
761 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
762 fname, section_table_bytes));
763 goto error_exit;
766 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
767 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
768 fname, byte_count));
769 goto error_exit;
772 /* Iterate the section table looking for the resource section ".rsrc" */
773 for (i = 0; i < num_sections; i++) {
774 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
776 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
777 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
778 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
780 SAFE_FREE(buf);
781 if ((buf=malloc(section_bytes)) == NULL) {
782 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
783 fname, section_bytes));
784 goto error_exit;
787 /* Seek to the start of the .rsrc section info */
788 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
789 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
790 fname, errno));
791 goto error_exit;
794 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
795 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
796 fname, byte_count));
797 goto error_exit;
800 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
801 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
802 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
803 /* Align to next long address */
804 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
806 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
807 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
808 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
810 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
811 fname, *major, *minor,
812 (*major>>16)&0xffff, *major&0xffff,
813 (*minor>>16)&0xffff, *minor&0xffff));
814 SAFE_FREE(buf);
815 return 1;
822 /* Version info not found, fall back to origin date/time */
823 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
824 SAFE_FREE(buf);
825 return 0;
827 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
828 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
829 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
830 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
831 /* At this point, we assume the file is in error. It still could be somthing
832 * else besides a NE file, but it unlikely at this point. */
833 goto error_exit;
836 /* Allocate a bit more space to speed up things */
837 SAFE_FREE(buf);
838 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
839 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
840 fname, PE_HEADER_SIZE));
841 goto error_exit;
844 /* This is a HACK! I got tired of trying to sort through the messy
845 * 'NE' file format. If anyone wants to clean this up please have at
846 * it, but this works. 'NE' files will eventually fade away. JRR */
847 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
848 /* Cover case that should not occur in a well formed 'NE' .dll file */
849 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
851 for(i=0; i<byte_count; i++) {
852 /* Fast skip past data that can't possibly match */
853 if (buf[i] != 'V') continue;
855 /* Potential match data crosses buf boundry, move it to beginning
856 * of buf, and fill the buf with as much as it will hold. */
857 if (i>byte_count-VS_VERSION_INFO_SIZE) {
858 int bc;
860 memcpy(buf, &buf[i], byte_count-i);
861 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
862 (byte_count-i))) < 0) {
864 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
865 fname, errno));
866 goto error_exit;
869 byte_count = bc + (byte_count - i);
870 if (byte_count<VS_VERSION_INFO_SIZE) break;
872 i = 0;
875 /* Check that the full signature string and the magic number that
876 * follows exist (not a perfect solution, but the chances that this
877 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
878 * twice, as it is simpler to read the code. */
879 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
880 /* Compute skip alignment to next long address */
881 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
882 sizeof(VS_SIGNATURE)) & 3;
883 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
885 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
886 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
887 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
888 fname, *major, *minor,
889 (*major>>16)&0xffff, *major&0xffff,
890 (*minor>>16)&0xffff, *minor&0xffff));
891 SAFE_FREE(buf);
892 return 1;
897 /* Version info not found, fall back to origin date/time */
898 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
899 SAFE_FREE(buf);
900 return 0;
902 } else
903 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
904 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
905 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
907 no_version_info:
908 SAFE_FREE(buf);
909 return 0;
911 error_exit:
912 SAFE_FREE(buf);
913 return -1;
916 /****************************************************************************
917 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
918 share one or more files. During the MS installation process files are checked
919 to insure that only a newer version of a shared file is installed over an
920 older version. There are several possibilities for this comparison. If there
921 is no previous version, the new one is newer (obviously). If either file is
922 missing the version info structure, compare the creation date (on Unix use
923 the modification date). Otherwise chose the numerically larger version number.
924 ****************************************************************************/
925 static int file_version_is_newer(connection_struct *conn, fstring new_file,
926 fstring old_file)
928 BOOL use_version = True;
929 pstring filepath;
931 uint32 new_major;
932 uint32 new_minor;
933 time_t new_create_time;
935 uint32 old_major;
936 uint32 old_minor;
937 time_t old_create_time;
939 int access_mode;
940 int action;
941 files_struct *fsp = NULL;
942 SMB_STRUCT_STAT st;
943 SMB_STRUCT_STAT stat_buf;
944 BOOL bad_path;
946 ZERO_STRUCT(st);
947 ZERO_STRUCT(stat_buf);
948 new_create_time = (time_t)0;
949 old_create_time = (time_t)0;
951 /* Get file version info (if available) for previous file (if it exists) */
952 pstrcpy(filepath, old_file);
954 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
956 fsp = open_file_shared(conn, filepath, &stat_buf,
957 SET_OPEN_MODE(DOS_OPEN_RDONLY),
958 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
959 0, 0, &access_mode, &action);
960 if (!fsp) {
961 /* Old file not found, so by definition new file is in fact newer */
962 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
963 filepath, errno));
964 return True;
966 } else {
967 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
968 if (ret == -1) goto error_exit;
970 if (!ret) {
971 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
972 old_file));
973 use_version = False;
975 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
976 old_create_time = st.st_mtime;
977 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
979 close_file(fsp, True);
981 /* Get file version info (if available) for new file */
982 pstrcpy(filepath, new_file);
983 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
985 fsp = open_file_shared(conn, filepath, &stat_buf,
986 SET_OPEN_MODE(DOS_OPEN_RDONLY),
987 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
988 0, 0, &access_mode, &action);
989 if (!fsp) {
990 /* New file not found, this shouldn't occur if the caller did its job */
991 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
992 filepath, errno));
993 goto error_exit;
995 } else {
996 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
997 if (ret == -1) goto error_exit;
999 if (!ret) {
1000 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1001 new_file));
1002 use_version = False;
1004 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1005 new_create_time = st.st_mtime;
1006 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1008 close_file(fsp, True);
1010 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1011 /* Compare versions and choose the larger version number */
1012 if (new_major > old_major ||
1013 (new_major == old_major && new_minor > old_minor)) {
1015 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1016 return True;
1018 else {
1019 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1020 return False;
1023 } else {
1024 /* Compare modification time/dates and choose the newest time/date */
1025 if (new_create_time > old_create_time) {
1026 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1027 return True;
1029 else {
1030 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1031 return False;
1035 error_exit:
1036 if(fsp)
1037 close_file(fsp, True);
1038 return -1;
1041 /****************************************************************************
1042 Determine the correct cVersion associated with an architecture and driver
1043 ****************************************************************************/
1044 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
1045 struct current_user *user, WERROR *perr)
1047 int cversion;
1048 int access_mode;
1049 int action;
1050 pstring driverpath;
1051 fstring user_name;
1052 fstring null_pw;
1053 fstring dev;
1054 fstring sharename;
1055 files_struct *fsp = NULL;
1056 BOOL bad_path;
1057 int ecode;
1058 SMB_STRUCT_STAT st;
1059 struct passwd *pass;
1060 connection_struct *conn;
1062 ZERO_STRUCT(st);
1064 *perr = WERR_INVALID_PARAM;
1066 /* If architecture is Windows 95/98/ME, the version is always 0. */
1067 if (strcmp(architecture, "WIN40") == 0) {
1068 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1069 *perr = WERR_OK;
1070 return 0;
1073 become_root();
1074 pass = sys_getpwuid(user->uid);
1075 if(pass == NULL) {
1076 DEBUG(0,("get_correct_cversion: Unable to get passwd entry for uid %u\n",
1077 (unsigned int)user->uid ));
1078 unbecome_root();
1079 *perr = WERR_ACCESS_DENIED;
1080 return -1;
1084 * Connect to the print$ share under the same account as the user connected
1085 * to the rpc pipe. Note we must still be root to do this.
1088 fstrcpy(user_name, pass->pw_name );
1089 DEBUG(10,("get_correct_cversion: uid %d -> user %s\n", (int)user->uid, user_name));
1091 /* Null password is ok - we are already an authenticated user... */
1092 *null_pw = '\0';
1093 fstrcpy(dev, "A:");
1094 fstrcpy(sharename, "print$");
1095 conn = make_connection(sharename, user_name, null_pw, 0, dev, user->vuid, &ecode);
1096 unbecome_root();
1098 if (conn == NULL) {
1099 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1100 *perr = W_ERROR(ecode);
1101 return -1;
1104 /* We are temporarily becoming the connection user. */
1105 if (!become_user(conn, conn->vuid)) {
1106 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1107 *perr = WERR_ACCESS_DENIED;
1108 return -1;
1111 /* Open the driver file (Portable Executable format) and determine the
1112 * deriver the cversion. */
1113 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1115 unix_convert(driverpath,conn,NULL,&bad_path,&st);
1117 fsp = open_file_shared(conn, driverpath, &st,
1118 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1119 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1120 0, 0, &access_mode, &action);
1121 if (!fsp) {
1122 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1123 driverpath, errno));
1124 *perr = WERR_ACCESS_DENIED;
1125 goto error_exit;
1127 else {
1128 uint32 major;
1129 uint32 minor;
1130 int ret = get_file_version(fsp, driverpath, &major, &minor);
1131 if (ret == -1) goto error_exit;
1133 if (!ret) {
1134 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1135 goto error_exit;
1139 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1140 * for more details. Version in this case is not just the version of the
1141 * file, but the version in the sense of kernal mode (2) vs. user mode
1142 * (3) drivers. Other bits of the version fields are the version info.
1143 * JRR 010716
1145 cversion = major & 0x0000ffff;
1146 switch (cversion) {
1147 case 2: /* WinNT drivers */
1148 case 3: /* Win2K drivers */
1149 break;
1151 default:
1152 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1153 driverpath, cversion));
1154 goto error_exit;
1157 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1158 driverpath, major, minor));
1161 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1162 driverpath, cversion));
1164 close_file(fsp, True);
1165 close_cnum(conn, user->vuid);
1166 unbecome_user();
1167 *perr = WERR_OK;
1168 return cversion;
1171 error_exit:
1173 if(fsp)
1174 close_file(fsp, True);
1176 close_cnum(conn, user->vuid);
1177 unbecome_user();
1178 return -1;
1181 /****************************************************************************
1182 ****************************************************************************/
1183 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1184 struct current_user *user)
1186 fstring architecture;
1187 fstring new_name;
1188 char *p;
1189 int i;
1190 WERROR err;
1192 /* clean up the driver name.
1193 * we can get .\driver.dll
1194 * or worse c:\windows\system\driver.dll !
1196 /* using an intermediate string to not have overlaping memcpy()'s */
1197 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1198 fstrcpy(new_name, p+1);
1199 fstrcpy(driver->driverpath, new_name);
1202 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1203 fstrcpy(new_name, p+1);
1204 fstrcpy(driver->datafile, new_name);
1207 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1208 fstrcpy(new_name, p+1);
1209 fstrcpy(driver->configfile, new_name);
1212 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1213 fstrcpy(new_name, p+1);
1214 fstrcpy(driver->helpfile, new_name);
1217 if (driver->dependentfiles) {
1218 for (i=0; *driver->dependentfiles[i]; i++) {
1219 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1220 fstrcpy(new_name, p+1);
1221 fstrcpy(driver->dependentfiles[i], new_name);
1226 get_short_archi(architecture, driver->environment);
1228 /* jfm:7/16/2000 the client always sends the cversion=0.
1229 * The server should check which version the driver is by reading
1230 * the PE header of driver->driverpath.
1232 * For Windows 95/98 the version is 0 (so the value sent is correct)
1233 * For Windows NT (the architecture doesn't matter)
1234 * NT 3.1: cversion=0
1235 * NT 3.5/3.51: cversion=1
1236 * NT 4: cversion=2
1237 * NT2K: cversion=3
1239 if ((driver->cversion = get_correct_cversion( architecture,
1240 driver->driverpath, user, &err)) == -1)
1241 return err;
1243 return WERR_OK;
1246 /****************************************************************************
1247 ****************************************************************************/
1248 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
1249 struct current_user *user)
1251 fstring architecture;
1252 fstring new_name;
1253 char *p;
1254 int i;
1255 WERROR err;
1257 /* clean up the driver name.
1258 * we can get .\driver.dll
1259 * or worse c:\windows\system\driver.dll !
1261 /* using an intermediate string to not have overlaping memcpy()'s */
1262 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1263 fstrcpy(new_name, p+1);
1264 fstrcpy(driver->driverpath, new_name);
1267 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1268 fstrcpy(new_name, p+1);
1269 fstrcpy(driver->datafile, new_name);
1272 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1273 fstrcpy(new_name, p+1);
1274 fstrcpy(driver->configfile, new_name);
1277 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1278 fstrcpy(new_name, p+1);
1279 fstrcpy(driver->helpfile, new_name);
1282 if (driver->dependentfiles) {
1283 for (i=0; *driver->dependentfiles[i]; i++) {
1284 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1285 fstrcpy(new_name, p+1);
1286 fstrcpy(driver->dependentfiles[i], new_name);
1291 get_short_archi(architecture, driver->environment);
1293 /* jfm:7/16/2000 the client always sends the cversion=0.
1294 * The server should check which version the driver is by reading
1295 * the PE header of driver->driverpath.
1297 * For Windows 95/98 the version is 0 (so the value sent is correct)
1298 * For Windows NT (the architecture doesn't matter)
1299 * NT 3.1: cversion=0
1300 * NT 3.5/3.51: cversion=1
1301 * NT 4: cversion=2
1302 * NT2K: cversion=3
1304 if ((driver->version = get_correct_cversion(architecture,
1305 driver->driverpath, user, &err)) == -1)
1306 return err;
1308 return WERR_OK;
1311 /****************************************************************************
1312 ****************************************************************************/
1313 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1314 uint32 level, struct current_user *user)
1316 switch (level) {
1317 case 3:
1319 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1320 driver=driver_abstract.info_3;
1321 return clean_up_driver_struct_level_3(driver, user);
1323 case 6:
1325 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1326 driver=driver_abstract.info_6;
1327 return clean_up_driver_struct_level_6(driver, user);
1329 default:
1330 return WERR_INVALID_PARAM;
1334 /****************************************************************************
1335 This function sucks and should be replaced. JRA.
1336 ****************************************************************************/
1338 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1340 dst->cversion = src->version;
1342 fstrcpy( dst->name, src->name);
1343 fstrcpy( dst->environment, src->environment);
1344 fstrcpy( dst->driverpath, src->driverpath);
1345 fstrcpy( dst->datafile, src->datafile);
1346 fstrcpy( dst->configfile, src->configfile);
1347 fstrcpy( dst->helpfile, src->helpfile);
1348 fstrcpy( dst->monitorname, src->monitorname);
1349 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1350 dst->dependentfiles = src->dependentfiles;
1353 #if 0 /* Debugging function */
1355 static char* ffmt(unsigned char *c){
1356 int i;
1357 static char ffmt_str[17];
1359 for (i=0; i<16; i++) {
1360 if ((c[i] < ' ') || (c[i] > '~'))
1361 ffmt_str[i]='.';
1362 else
1363 ffmt_str[i]=c[i];
1365 ffmt_str[16]='\0';
1366 return ffmt_str;
1369 #endif
1371 /****************************************************************************
1372 ****************************************************************************/
1373 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1374 struct current_user *user, WERROR *perr)
1376 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1377 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1378 fstring architecture;
1379 pstring new_dir;
1380 pstring old_name;
1381 pstring new_name;
1382 fstring user_name;
1383 fstring null_pw;
1384 fstring dev;
1385 fstring sharename;
1386 connection_struct *conn;
1387 pstring inbuf;
1388 pstring outbuf;
1389 struct passwd *pass;
1390 int ecode;
1391 int ver = 0;
1392 int i;
1394 memset(inbuf, '\0', sizeof(inbuf));
1395 memset(outbuf, '\0', sizeof(outbuf));
1396 *perr = WERR_OK;
1398 if (level==3)
1399 driver=driver_abstract.info_3;
1400 else if (level==6) {
1401 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1402 driver = &converted_driver;
1403 } else {
1404 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1405 return False;
1408 get_short_archi(architecture, driver->environment);
1410 become_root();
1411 pass = sys_getpwuid(user->uid);
1412 if(pass == NULL) {
1413 DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n",
1414 (unsigned int)user->uid ));
1415 unbecome_root();
1416 return False;
1420 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1421 * Note we must be root to do this.
1424 fstrcpy(user_name, pass->pw_name );
1425 DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
1427 /* Null password is ok - we are already an authenticated user... */
1428 *null_pw = '\0';
1429 fstrcpy(dev, "A:");
1430 fstrcpy(sharename, "print$");
1431 conn = make_connection(sharename, user_name, null_pw, 0, dev, user->vuid, &ecode);
1432 unbecome_root();
1434 if (conn == NULL) {
1435 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1436 *perr = W_ERROR(ecode);
1437 return False;
1441 * Save who we are - we are temporarily becoming the connection user.
1444 if (!become_user(conn, conn->vuid)) {
1445 DEBUG(0,("move_driver_to_download_area: Can't become user %s\n", user_name ));
1446 return False;
1450 * make the directories version and version\driver_name
1451 * under the architecture directory.
1453 DEBUG(5,("Creating first directory\n"));
1454 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1455 mkdir_internal(conn, new_dir);
1457 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1458 * listed for this driver which has already been moved, skip it (note:
1459 * drivers may list the same file name several times. Then check if the
1460 * file already exists in archi\cversion\, if so, check that the version
1461 * info (or time stamps if version info is unavailable) is newer (or the
1462 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1463 * Otherwise, delete the file.
1465 * If a file is not moved to archi\cversion\ because of an error, all the
1466 * rest of the 'unmoved' driver files are removed from archi\. If one or
1467 * more of the driver's files was already moved to archi\cversion\, it
1468 * potentially leaves the driver in a partially updated state. Version
1469 * trauma will most likely occur if an client attempts to use any printer
1470 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1471 * done is appropriate... later JRR
1474 DEBUG(5,("Moving files now !\n"));
1476 if (driver->driverpath && strlen(driver->driverpath)) {
1477 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1478 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1479 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1480 NTSTATUS status;
1481 status = rename_internals(conn, new_name, old_name, True);
1482 if (!NT_STATUS_IS_OK(status)) {
1483 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1484 new_name, old_name));
1485 *perr = ntstatus_to_werror(status);
1486 unlink_internals(conn, 0, new_name);
1487 ver = -1;
1490 else
1491 unlink_internals(conn, 0, new_name);
1494 if (driver->datafile && strlen(driver->datafile)) {
1495 if (!strequal(driver->datafile, driver->driverpath)) {
1496 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1497 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1498 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1499 NTSTATUS status;
1500 status = rename_internals(conn, new_name, old_name, True);
1501 if (!NT_STATUS_IS_OK(status)) {
1502 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1503 new_name, old_name));
1504 *perr = ntstatus_to_werror(status);
1505 unlink_internals(conn, 0, new_name);
1506 ver = -1;
1509 else
1510 unlink_internals(conn, 0, new_name);
1514 if (driver->configfile && strlen(driver->configfile)) {
1515 if (!strequal(driver->configfile, driver->driverpath) &&
1516 !strequal(driver->configfile, driver->datafile)) {
1517 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1518 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1519 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1520 NTSTATUS status;
1521 status = rename_internals(conn, new_name, old_name, True);
1522 if (!NT_STATUS_IS_OK(status)) {
1523 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1524 new_name, old_name));
1525 *perr = ntstatus_to_werror(status);
1526 unlink_internals(conn, 0, new_name);
1527 ver = -1;
1530 else
1531 unlink_internals(conn, 0, new_name);
1535 if (driver->helpfile && strlen(driver->helpfile)) {
1536 if (!strequal(driver->helpfile, driver->driverpath) &&
1537 !strequal(driver->helpfile, driver->datafile) &&
1538 !strequal(driver->helpfile, driver->configfile)) {
1539 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1540 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1541 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1542 NTSTATUS status;
1543 status = rename_internals(conn, new_name, old_name, True);
1544 if (!NT_STATUS_IS_OK(status)) {
1545 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1546 new_name, old_name));
1547 *perr = ntstatus_to_werror(status);
1548 unlink_internals(conn, 0, new_name);
1549 ver = -1;
1552 else
1553 unlink_internals(conn, 0, new_name);
1557 if (driver->dependentfiles) {
1558 for (i=0; *driver->dependentfiles[i]; i++) {
1559 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1560 !strequal(driver->dependentfiles[i], driver->datafile) &&
1561 !strequal(driver->dependentfiles[i], driver->configfile) &&
1562 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1563 int j;
1564 for (j=0; j < i; j++) {
1565 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1566 goto NextDriver;
1570 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1571 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1572 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1573 NTSTATUS status;
1574 status = rename_internals(conn, new_name, old_name, True);
1575 if (!NT_STATUS_IS_OK(status)) {
1576 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1577 new_name, old_name));
1578 *perr = ntstatus_to_werror(status);
1579 unlink_internals(conn, 0, new_name);
1580 ver = -1;
1583 else
1584 unlink_internals(conn, 0, new_name);
1586 NextDriver: ;
1590 close_cnum(conn, user->vuid);
1591 unbecome_user();
1593 return ver == -1 ? False : True;
1596 /****************************************************************************
1597 ****************************************************************************/
1598 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1600 int len, buflen;
1601 fstring architecture;
1602 pstring directory;
1603 pstring temp_name;
1604 pstring key;
1605 char *buf;
1606 int i, ret;
1607 TDB_DATA kbuf, dbuf;
1609 get_short_archi(architecture, driver->environment);
1611 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1612 * \\server is added in the rpc server layer.
1613 * It does make sense to NOT store the server's name in the printer TDB.
1616 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1618 /* .inf files do not always list a file for each of the four standard files.
1619 * Don't prepend a path to a null filename, or client claims:
1620 * "The server on which the printer resides does not have a suitable
1621 * <printer driver name> printer driver installed. Click OK if you
1622 * wish to install the driver on your local machine."
1624 if (strlen(driver->driverpath)) {
1625 fstrcpy(temp_name, driver->driverpath);
1626 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1629 if (strlen(driver->datafile)) {
1630 fstrcpy(temp_name, driver->datafile);
1631 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1634 if (strlen(driver->configfile)) {
1635 fstrcpy(temp_name, driver->configfile);
1636 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1639 if (strlen(driver->helpfile)) {
1640 fstrcpy(temp_name, driver->helpfile);
1641 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1644 if (driver->dependentfiles) {
1645 for (i=0; *driver->dependentfiles[i]; i++) {
1646 fstrcpy(temp_name, driver->dependentfiles[i]);
1647 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1651 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1652 dos_to_unix(key); /* Convert key to unix-codepage */
1654 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1656 buf = NULL;
1657 len = buflen = 0;
1659 again:
1660 len = 0;
1661 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1662 driver->cversion,
1663 driver->name,
1664 driver->environment,
1665 driver->driverpath,
1666 driver->datafile,
1667 driver->configfile,
1668 driver->helpfile,
1669 driver->monitorname,
1670 driver->defaultdatatype);
1672 if (driver->dependentfiles) {
1673 for (i=0; *driver->dependentfiles[i]; i++) {
1674 len += tdb_pack(buf+len, buflen-len, "f",
1675 driver->dependentfiles[i]);
1679 if (len != buflen) {
1680 char *tb;
1682 tb = (char *)Realloc(buf, len);
1683 if (!tb) {
1684 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1685 ret = -1;
1686 goto done;
1688 else buf = tb;
1689 buflen = len;
1690 goto again;
1694 kbuf.dptr = key;
1695 kbuf.dsize = strlen(key)+1;
1696 dbuf.dptr = buf;
1697 dbuf.dsize = len;
1699 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1701 done:
1702 if (ret)
1703 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1705 SAFE_FREE(buf);
1706 return ret;
1709 /****************************************************************************
1710 ****************************************************************************/
1711 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1713 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1715 ZERO_STRUCT(info3);
1716 info3.cversion = driver->version;
1717 fstrcpy(info3.name,driver->name);
1718 fstrcpy(info3.environment,driver->environment);
1719 fstrcpy(info3.driverpath,driver->driverpath);
1720 fstrcpy(info3.datafile,driver->datafile);
1721 fstrcpy(info3.configfile,driver->configfile);
1722 fstrcpy(info3.helpfile,driver->helpfile);
1723 fstrcpy(info3.monitorname,driver->monitorname);
1724 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1725 info3.dependentfiles = driver->dependentfiles;
1727 return add_a_printer_driver_3(&info3);
1731 /****************************************************************************
1732 ****************************************************************************/
1733 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const fstring in_prt, const fstring in_arch)
1735 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1737 ZERO_STRUCT(info);
1739 fstrcpy(info.name, in_prt);
1740 fstrcpy(info.defaultdatatype, "RAW");
1742 fstrcpy(info.driverpath, "");
1743 fstrcpy(info.datafile, "");
1744 fstrcpy(info.configfile, "");
1745 fstrcpy(info.helpfile, "");
1747 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1748 return WERR_NOMEM;
1750 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1751 fstrcpy(info.dependentfiles[0], "");
1753 *info_ptr = memdup(&info, sizeof(info));
1755 return WERR_OK;
1758 /****************************************************************************
1759 ****************************************************************************/
1760 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const fstring in_prt, const fstring in_arch, uint32 version)
1762 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1763 TDB_DATA kbuf, dbuf;
1764 fstring architecture;
1765 int len = 0;
1766 int i;
1767 pstring key;
1769 ZERO_STRUCT(driver);
1771 get_short_archi(architecture, in_arch);
1773 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1775 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1777 kbuf.dptr = key;
1778 kbuf.dsize = strlen(key)+1;
1780 dbuf = tdb_fetch(tdb_drivers, kbuf);
1781 if (!dbuf.dptr)
1782 return WERR_UNKNOWN_PRINTER_DRIVER;
1784 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1785 &driver.cversion,
1786 driver.name,
1787 driver.environment,
1788 driver.driverpath,
1789 driver.datafile,
1790 driver.configfile,
1791 driver.helpfile,
1792 driver.monitorname,
1793 driver.defaultdatatype);
1795 i=0;
1796 while (len < dbuf.dsize) {
1797 fstring *tddfs;
1799 tddfs = (fstring *)Realloc(driver.dependentfiles,
1800 sizeof(fstring)*(i+2));
1801 if (tddfs == NULL) {
1802 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1803 break;
1805 else driver.dependentfiles = tddfs;
1807 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1808 &driver.dependentfiles[i]);
1809 i++;
1811 if (driver.dependentfiles != NULL)
1812 fstrcpy(driver.dependentfiles[i], "");
1814 SAFE_FREE(dbuf.dptr);
1816 if (len != dbuf.dsize) {
1817 SAFE_FREE(driver.dependentfiles);
1819 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1822 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1824 return WERR_OK;
1827 /****************************************************************************
1828 ****************************************************************************/
1829 uint32 get_a_printer_driver_9x_compatible(pstring line, const fstring model)
1831 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1832 TDB_DATA kbuf;
1833 pstring key;
1834 int i;
1835 line[0] = '\0';
1837 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1838 DEBUG(10,("driver key: [%s]\n", key));
1840 kbuf.dptr = key;
1841 kbuf.dsize = strlen(key)+1;
1842 if (!tdb_exists(tdb_drivers, kbuf))
1843 return False;
1845 ZERO_STRUCT(info3);
1846 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1848 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1849 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1850 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1851 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1852 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1853 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1854 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1856 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1857 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1858 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1860 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1861 trim_string(info3->driverpath, "\\print$\\WIN40\\0\\", 0);
1862 pstrcat(line, info3->driverpath);
1863 pstrcat(line, ":");
1864 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1865 pstrcat(line, info3->datafile);
1866 pstrcat(line, ":");
1867 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1868 pstrcat(line, info3->helpfile);
1869 pstrcat(line, ":");
1870 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1871 pstrcat(line, info3->monitorname);
1872 pstrcat(line, ":");
1873 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1874 pstrcat(line, ":");
1876 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1877 if (i)
1878 pstrcat(line, ","); /* don't end in a "," */
1879 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1880 pstrcat(line, info3->dependentfiles[i]);
1883 SAFE_FREE(info3);
1885 return True;
1888 /****************************************************************************
1889 Debugging function, dump at level 6 the struct in the logs.
1890 ****************************************************************************/
1892 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1894 uint32 result;
1895 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1896 int i;
1898 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1900 switch (level)
1902 case 3:
1904 if (driver.info_3 == NULL)
1905 result=5;
1906 else {
1907 info3=driver.info_3;
1909 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1910 DEBUGADD(106,("name:[%s]\n", info3->name));
1911 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1912 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1913 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1914 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1915 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1916 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1917 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1919 for (i=0; info3->dependentfiles &&
1920 *info3->dependentfiles[i]; i++) {
1921 DEBUGADD(106,("dependentfile:[%s]\n",
1922 info3->dependentfiles[i]));
1924 result=0;
1926 break;
1928 default:
1929 DEBUGADD(106,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1930 result=1;
1931 break;
1934 return result;
1937 /****************************************************************************
1938 ****************************************************************************/
1939 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1941 int len = 0;
1943 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1945 if (!nt_devmode) return len;
1947 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1948 nt_devmode->devicename,
1949 nt_devmode->formname,
1951 nt_devmode->specversion,
1952 nt_devmode->driverversion,
1953 nt_devmode->size,
1954 nt_devmode->driverextra,
1955 nt_devmode->orientation,
1956 nt_devmode->papersize,
1957 nt_devmode->paperlength,
1958 nt_devmode->paperwidth,
1959 nt_devmode->scale,
1960 nt_devmode->copies,
1961 nt_devmode->defaultsource,
1962 nt_devmode->printquality,
1963 nt_devmode->color,
1964 nt_devmode->duplex,
1965 nt_devmode->yresolution,
1966 nt_devmode->ttoption,
1967 nt_devmode->collate,
1968 nt_devmode->logpixels,
1970 nt_devmode->fields,
1971 nt_devmode->bitsperpel,
1972 nt_devmode->pelswidth,
1973 nt_devmode->pelsheight,
1974 nt_devmode->displayflags,
1975 nt_devmode->displayfrequency,
1976 nt_devmode->icmmethod,
1977 nt_devmode->icmintent,
1978 nt_devmode->mediatype,
1979 nt_devmode->dithertype,
1980 nt_devmode->reserved1,
1981 nt_devmode->reserved2,
1982 nt_devmode->panningwidth,
1983 nt_devmode->panningheight,
1984 nt_devmode->private);
1987 if (nt_devmode->private) {
1988 len += tdb_pack(buf+len, buflen-len, "B",
1989 nt_devmode->driverextra,
1990 nt_devmode->private);
1993 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1995 return len;
1998 /****************************************************************************
1999 ****************************************************************************/
2000 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
2002 int len = 0;
2004 while (param != NULL) {
2005 len += tdb_pack(buf+len, buflen-len, "pfdB",
2006 param,
2007 param->value,
2008 param->type,
2009 param->data_len,
2010 param->data);
2011 param=param->next;
2014 len += tdb_pack(buf+len, buflen-len, "p", param);
2016 return len;
2020 /****************************************************************************
2021 Delete a printer - this just deletes the printer info file, any open
2022 handles are not affected.
2023 ****************************************************************************/
2025 uint32 del_a_printer(char *sharename)
2027 pstring key;
2028 TDB_DATA kbuf;
2030 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2031 dos_to_unix(key); /* Convert key to unix-codepage */
2033 kbuf.dptr=key;
2034 kbuf.dsize=strlen(key)+1;
2036 tdb_delete(tdb_printers, kbuf);
2037 return 0;
2040 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
2041 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
2042 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
2043 /****************************************************************************
2044 ****************************************************************************/
2045 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2047 pstring key;
2048 char *buf;
2049 int buflen, len;
2050 WERROR ret;
2051 TDB_DATA kbuf, dbuf;
2054 * in addprinter: no servername and the printer is the name
2055 * in setprinter: servername is \\server
2056 * and printer is \\server\\printer
2058 * Samba manages only local printers.
2059 * we currently don't support things like path=\\other_server\printer
2062 if (info->servername[0]!='\0') {
2063 trim_string(info->printername, info->servername, NULL);
2064 trim_string(info->printername, "\\", NULL);
2065 info->servername[0]='\0';
2069 * JFM: one day I'll forget.
2070 * below that's info->portname because that's the SAMBA sharename
2071 * and I made NT 'thinks' it's the portname
2072 * the info->sharename is the thing you can name when you add a printer
2073 * that's the short-name when you create shared printer for 95/98
2074 * So I've made a limitation in SAMBA: you can only have 1 printer model
2075 * behind a SAMBA share.
2078 buf = NULL;
2079 buflen = 0;
2081 again:
2082 len = 0;
2083 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2084 info->attributes,
2085 info->priority,
2086 info->default_priority,
2087 info->starttime,
2088 info->untiltime,
2089 info->status,
2090 info->cjobs,
2091 info->averageppm,
2092 info->changeid,
2093 info->c_setprinter,
2094 info->setuptime,
2095 info->servername,
2096 info->printername,
2097 info->sharename,
2098 info->portname,
2099 info->drivername,
2100 info->comment,
2101 info->location,
2102 info->sepfile,
2103 info->printprocessor,
2104 info->datatype,
2105 info->parameters);
2107 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2109 len += pack_specifics(info->specific, buf+len, buflen-len);
2111 if (buflen != len) {
2112 char *tb;
2114 tb = (char *)Realloc(buf, len);
2115 if (!tb) {
2116 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2117 ret = WERR_NOMEM;
2118 goto done;
2120 else buf = tb;
2121 buflen = len;
2122 goto again;
2126 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2127 dos_to_unix(key); /* Convert key to unix-codepage */
2129 kbuf.dptr = key;
2130 kbuf.dsize = strlen(key)+1;
2131 dbuf.dptr = buf;
2132 dbuf.dsize = len;
2134 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2136 done:
2137 if (!W_ERROR_IS_OK(ret))
2138 DEBUG(8, ("error updating printer to tdb on disk\n"));
2140 SAFE_FREE(buf);
2142 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2143 info->sharename, info->drivername, info->portname, len));
2145 return ret;
2149 /****************************************************************************
2150 ****************************************************************************/
2151 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
2153 NT_PRINTER_PARAM *current;
2155 DEBUG(108,("add_a_specific_param\n"));
2157 (*param)->next=NULL;
2159 if (info_2->specific == NULL)
2161 info_2->specific=*param;
2163 else
2165 current=info_2->specific;
2166 while (current->next != NULL) {
2167 current=current->next;
2169 current->next=*param;
2172 *param = NULL;
2175 /****************************************************************************
2176 ****************************************************************************/
2177 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
2179 NT_PRINTER_PARAM *current;
2180 NT_PRINTER_PARAM *previous;
2182 current=info_2->specific;
2183 previous=current;
2185 if (current==NULL) return (False);
2187 if ( !strcmp(current->value, param->value) &&
2188 (strlen(current->value)==strlen(param->value)) ) {
2189 DEBUG(109,("deleting first value\n"));
2190 info_2->specific=current->next;
2191 SAFE_FREE(current->data);
2192 SAFE_FREE(current);
2193 DEBUG(109,("deleted first value\n"));
2194 return (True);
2197 current=previous->next;
2199 while ( current!=NULL ) {
2200 if (!strcmp(current->value, param->value) &&
2201 strlen(current->value)==strlen(param->value) ) {
2202 DEBUG(109,("deleting current value\n"));
2203 previous->next=current->next;
2204 SAFE_FREE(current->data);
2205 SAFE_FREE(current);
2206 DEBUG(109,("deleted current value\n"));
2207 return(True);
2210 previous=previous->next;
2211 current=current->next;
2213 return (False);
2216 /****************************************************************************
2217 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2218 ****************************************************************************/
2219 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2221 NT_PRINTER_PARAM *param = *param_ptr;
2223 if(param == NULL)
2224 return;
2226 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2228 SAFE_FREE(param->data);
2229 SAFE_FREE(*param_ptr);
2232 /****************************************************************************
2233 Malloc and return an NT devicemode.
2234 ****************************************************************************/
2236 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2239 char adevice[MAXDEVICENAME+1];
2240 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2242 if (nt_devmode == NULL) {
2243 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2244 return NULL;
2247 ZERO_STRUCTP(nt_devmode);
2249 safe_strcpy(adevice, default_devicename, sizeof(adevice)-1);
2250 fstrcpy(nt_devmode->devicename, adevice);
2252 fstrcpy(nt_devmode->formname, "Letter");
2254 nt_devmode->specversion = 0x0401;
2255 nt_devmode->driverversion = 0x0400;
2256 nt_devmode->size = 0x00DC;
2257 nt_devmode->driverextra = 0x0000;
2258 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2259 DEFAULTSOURCE | COPIES | SCALE |
2260 PAPERSIZE | ORIENTATION;
2261 nt_devmode->orientation = 1;
2262 nt_devmode->papersize = PAPER_LETTER;
2263 nt_devmode->paperlength = 0;
2264 nt_devmode->paperwidth = 0;
2265 nt_devmode->scale = 0x64;
2266 nt_devmode->copies = 1;
2267 nt_devmode->defaultsource = BIN_FORMSOURCE;
2268 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2269 nt_devmode->color = COLOR_MONOCHROME;
2270 nt_devmode->duplex = DUP_SIMPLEX;
2271 nt_devmode->yresolution = 0;
2272 nt_devmode->ttoption = TT_SUBDEV;
2273 nt_devmode->collate = COLLATE_FALSE;
2274 nt_devmode->icmmethod = 0;
2275 nt_devmode->icmintent = 0;
2276 nt_devmode->mediatype = 0;
2277 nt_devmode->dithertype = 0;
2279 /* non utilisés par un driver d'imprimante */
2280 nt_devmode->logpixels = 0;
2281 nt_devmode->bitsperpel = 0;
2282 nt_devmode->pelswidth = 0;
2283 nt_devmode->pelsheight = 0;
2284 nt_devmode->displayflags = 0;
2285 nt_devmode->displayfrequency = 0;
2286 nt_devmode->reserved1 = 0;
2287 nt_devmode->reserved2 = 0;
2288 nt_devmode->panningwidth = 0;
2289 nt_devmode->panningheight = 0;
2291 nt_devmode->private = NULL;
2292 return nt_devmode;
2295 /****************************************************************************
2296 Deepcopy an NT devicemode.
2297 ****************************************************************************/
2299 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2301 NT_DEVICEMODE *new_nt_devicemode = NULL;
2303 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2304 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2305 return NULL;
2308 new_nt_devicemode->private = NULL;
2309 if (nt_devicemode->private != NULL) {
2310 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2311 SAFE_FREE(new_nt_devicemode);
2312 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2313 return NULL;
2317 return new_nt_devicemode;
2320 /****************************************************************************
2321 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2322 ****************************************************************************/
2324 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2326 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2328 if(nt_devmode == NULL)
2329 return;
2331 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2333 SAFE_FREE(nt_devmode->private);
2334 SAFE_FREE(*devmode_ptr);
2337 /****************************************************************************
2338 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2339 ****************************************************************************/
2340 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2342 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2343 NT_PRINTER_PARAM *param_ptr;
2345 if(info == NULL)
2346 return;
2348 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2350 free_nt_devicemode(&info->devmode);
2352 for(param_ptr = info->specific; param_ptr; ) {
2353 NT_PRINTER_PARAM *tofree = param_ptr;
2355 param_ptr = param_ptr->next;
2356 free_nt_printer_param(&tofree);
2359 SAFE_FREE(*info_ptr);
2363 /****************************************************************************
2364 ****************************************************************************/
2365 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2367 int len = 0;
2368 int extra_len = 0;
2369 NT_DEVICEMODE devmode;
2371 ZERO_STRUCT(devmode);
2373 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2375 if (!*nt_devmode) return len;
2377 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2378 devmode.devicename,
2379 devmode.formname,
2381 &devmode.specversion,
2382 &devmode.driverversion,
2383 &devmode.size,
2384 &devmode.driverextra,
2385 &devmode.orientation,
2386 &devmode.papersize,
2387 &devmode.paperlength,
2388 &devmode.paperwidth,
2389 &devmode.scale,
2390 &devmode.copies,
2391 &devmode.defaultsource,
2392 &devmode.printquality,
2393 &devmode.color,
2394 &devmode.duplex,
2395 &devmode.yresolution,
2396 &devmode.ttoption,
2397 &devmode.collate,
2398 &devmode.logpixels,
2400 &devmode.fields,
2401 &devmode.bitsperpel,
2402 &devmode.pelswidth,
2403 &devmode.pelsheight,
2404 &devmode.displayflags,
2405 &devmode.displayfrequency,
2406 &devmode.icmmethod,
2407 &devmode.icmintent,
2408 &devmode.mediatype,
2409 &devmode.dithertype,
2410 &devmode.reserved1,
2411 &devmode.reserved2,
2412 &devmode.panningwidth,
2413 &devmode.panningheight,
2414 &devmode.private);
2416 if (devmode.private) {
2417 /* the len in tdb_unpack is an int value and
2418 * devmode.driverextra is only a short
2420 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2421 devmode.driverextra=(uint16)extra_len;
2423 /* check to catch an invalid TDB entry so we don't segfault */
2424 if (devmode.driverextra == 0) {
2425 devmode.private = NULL;
2429 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2431 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2432 if (devmode.private)
2433 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2435 return len;
2438 /****************************************************************************
2439 ****************************************************************************/
2440 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2442 int len = 0;
2443 NT_PRINTER_PARAM param, *p;
2445 *list = NULL;
2447 while (1) {
2448 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2449 if (!p) break;
2451 len += tdb_unpack(buf+len, buflen-len, "fdB",
2452 param.value,
2453 &param.type,
2454 &param.data_len,
2455 &param.data);
2456 param.next = *list;
2457 *list = memdup(&param, sizeof(param));
2459 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2462 return len;
2465 static void map_to_os2_driver(fstring drivername)
2467 static BOOL initialised=False;
2468 static fstring last_from,last_to;
2469 char *mapfile = lp_os2_driver_map();
2470 char **lines = NULL;
2471 int numlines = 0;
2472 int i;
2474 if (!strlen(drivername))
2475 return;
2477 if (!*mapfile)
2478 return;
2480 if (!initialised) {
2481 *last_from = *last_to = 0;
2482 initialised = True;
2485 if (strequal(drivername,last_from)) {
2486 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2487 fstrcpy(drivername,last_to);
2488 return;
2491 lines = file_lines_load(mapfile, &numlines, True);
2492 if (numlines == 0) {
2493 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2494 return;
2497 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2499 for( i = 0; i < numlines; i++) {
2500 char *nt_name = lines[i];
2501 char *os2_name = strchr(nt_name,'=');
2503 if (!os2_name)
2504 continue;
2506 *os2_name++ = 0;
2508 while (isspace(*nt_name))
2509 nt_name++;
2511 if (!*nt_name || strchr("#;",*nt_name))
2512 continue;
2515 int l = strlen(nt_name);
2516 while (l && isspace(nt_name[l-1])) {
2517 nt_name[l-1] = 0;
2518 l--;
2522 while (isspace(*os2_name))
2523 os2_name++;
2526 int l = strlen(os2_name);
2527 while (l && isspace(os2_name[l-1])) {
2528 os2_name[l-1] = 0;
2529 l--;
2533 if (strequal(nt_name,drivername)) {
2534 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2535 fstrcpy(last_from,drivername);
2536 fstrcpy(last_to,os2_name);
2537 fstrcpy(drivername,os2_name);
2538 file_lines_free(lines);
2539 return;
2543 file_lines_free(lines);
2546 /****************************************************************************
2547 get a default printer info 2 struct
2548 ****************************************************************************/
2549 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2551 int snum;
2552 NT_PRINTER_INFO_LEVEL_2 info;
2554 ZERO_STRUCT(info);
2556 snum = lp_servicenumber(sharename);
2558 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2559 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2560 get_called_name(), sharename);
2561 fstrcpy(info.sharename, sharename);
2562 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2563 fstrcpy(info.drivername, lp_printerdriver(snum));
2565 /* by setting the driver name to an empty string, a local NT admin
2566 can now run the **local** APW to install a local printer driver
2567 for a Samba shared printer in 2.2. Without this, drivers **must** be
2568 installed on the Samba server for NT clients --jerry */
2569 #if 0 /* JERRY --do not uncomment-- */
2570 if (!*info.drivername)
2571 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2572 #endif
2575 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2577 pstrcpy(info.comment, "");
2578 fstrcpy(info.printprocessor, "winprint");
2579 fstrcpy(info.datatype, "RAW");
2581 info.attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK; /* attributes */
2583 info.starttime = 0; /* Minutes since 12:00am GMT */
2584 info.untiltime = 0; /* Minutes since 12:00am GMT */
2585 info.priority = 1;
2586 info.default_priority = 1;
2587 info.setuptime = (uint32)time(NULL);
2590 * I changed this as I think it is better to have a generic
2591 * DEVMODE than to crash Win2k explorer.exe --jerry
2592 * See the HP Deskjet 990c Win2k drivers for an example.
2594 * However the default devmode appears to cause problems
2595 * with the HP CLJ 8500 PCL driver. Hence the addition of
2596 * the "default devmode" parameter --jerry 22/01/2002
2599 if (lp_default_devmode(snum)) {
2600 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2601 goto fail;
2603 else {
2604 info.devmode = NULL;
2607 /* This will get the current RPC talloc context, but we should be
2608 passing this as a parameter... fixme... JRA ! */
2610 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2611 goto fail;
2613 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2614 if (! *info_ptr) {
2615 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2616 goto fail;
2619 return WERR_OK;
2621 fail:
2622 if (info.devmode)
2623 free_nt_devicemode(&info.devmode);
2624 return WERR_ACCESS_DENIED;
2627 /****************************************************************************
2628 ****************************************************************************/
2629 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2631 pstring key;
2632 NT_PRINTER_INFO_LEVEL_2 info;
2633 int len = 0;
2634 TDB_DATA kbuf, dbuf;
2635 fstring printername;
2637 ZERO_STRUCT(info);
2639 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2640 dos_to_unix(key); /* Convert key to unix-codepage */
2642 kbuf.dptr = key;
2643 kbuf.dsize = strlen(key)+1;
2645 dbuf = tdb_fetch(tdb_printers, kbuf);
2646 if (!dbuf.dptr)
2647 return get_a_printer_2_default(info_ptr, sharename);
2649 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2650 &info.attributes,
2651 &info.priority,
2652 &info.default_priority,
2653 &info.starttime,
2654 &info.untiltime,
2655 &info.status,
2656 &info.cjobs,
2657 &info.averageppm,
2658 &info.changeid,
2659 &info.c_setprinter,
2660 &info.setuptime,
2661 info.servername,
2662 info.printername,
2663 info.sharename,
2664 info.portname,
2665 info.drivername,
2666 info.comment,
2667 info.location,
2668 info.sepfile,
2669 info.printprocessor,
2670 info.datatype,
2671 info.parameters);
2673 /* Samba has to have shared raw drivers. */
2674 info.attributes |= (PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK);
2676 /* Restore the stripped strings. */
2677 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2678 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
2679 info.printername);
2680 fstrcpy(info.printername, printername);
2682 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2685 * Some client drivers freak out if there is a NULL devmode
2686 * (probably the driver is not checking before accessing
2687 * the devmode pointer) --jerry
2689 * See comments in get_a_printer_2_default()
2692 if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode)
2694 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
2695 printername));
2696 info.devmode = construct_nt_devicemode(printername);
2699 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2701 /* This will get the current RPC talloc context, but we should be
2702 passing this as a parameter... fixme... JRA ! */
2704 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2706 /* Fix for OS/2 drivers. */
2708 if (get_remote_arch() == RA_OS2)
2709 map_to_os2_driver(info.drivername);
2711 SAFE_FREE(dbuf.dptr);
2712 *info_ptr=memdup(&info, sizeof(info));
2714 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2715 sharename, info.printername, info.drivername));
2717 return WERR_OK;
2720 /****************************************************************************
2721 debugging function, dump at level 6 the struct in the logs
2722 ****************************************************************************/
2723 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2725 uint32 result;
2726 NT_PRINTER_INFO_LEVEL_2 *info2;
2728 DEBUG(106,("Dumping printer at level [%d]\n", level));
2730 switch (level)
2732 case 2:
2734 if (printer.info_2 == NULL)
2735 result=5;
2736 else
2738 info2=printer.info_2;
2740 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2741 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2742 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2743 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2744 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2745 DEBUGADD(106,("status:[%d]\n", info2->status));
2746 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2747 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2748 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2749 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2750 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2752 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2753 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2754 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2755 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2756 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2757 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2758 DEBUGADD(106,("location:[%s]\n", info2->location));
2759 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2760 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2761 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2762 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2763 result=0;
2765 break;
2767 default:
2768 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
2769 result=1;
2770 break;
2773 return result;
2776 /****************************************************************************
2777 Get the parameters we can substitute in an NT print job.
2778 ****************************************************************************/
2780 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2782 NT_PRINTER_INFO_LEVEL *printer = NULL;
2784 **printername = **sharename = **portname = '\0';
2786 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2787 return;
2789 fstrcpy(*printername, printer->info_2->printername);
2790 fstrcpy(*sharename, printer->info_2->sharename);
2791 fstrcpy(*portname, printer->info_2->portname);
2793 free_a_printer(&printer, 2);
2796 /****************************************************************************
2797 Update the changeid time.
2798 This is SO NASTY as some drivers need this to change, others need it
2799 static. This value will change every second, and I must hope that this
2800 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
2801 UTAH ! JRA.
2802 ****************************************************************************/
2804 static uint32 rev_changeid(void)
2806 struct timeval tv;
2808 get_process_uptime(&tv);
2810 #if 1 /* JERRY */
2811 /* Return changeid as msec since spooler restart */
2812 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
2813 #else
2815 * This setting seems to work well but is too untested
2816 * to replace the above calculation. Left in for experiementation
2817 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
2819 return tv.tv_sec * 10 + tv.tv_usec / 100000;
2820 #endif
2824 * The function below are the high level ones.
2825 * only those ones must be called from the spoolss code.
2826 * JFM.
2829 /****************************************************************************
2830 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2831 ****************************************************************************/
2833 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2835 WERROR result;
2837 dump_a_printer(printer, level);
2839 switch (level)
2841 case 2:
2844 * Update the changestamp. Emperical tests show that the
2845 * ChangeID is always updated,but c_setprinter is
2846 * global spooler variable (not per printer).
2849 /* ChangeID **must** be increasing over the lifetime
2850 of client's spoolss service in order for the
2851 client's cache to show updates */
2853 printer.info_2->changeid = rev_changeid();
2856 * Because one day someone will ask:
2857 * NT->NT An admin connection to a remote
2858 * printer show changes imeediately in
2859 * the properities dialog
2861 * A non-admin connection will only show the
2862 * changes after viewing the properites page
2863 * 2 times. Seems to be related to a
2864 * race condition in the client between the spooler
2865 * updating the local cache and the Explorer.exe GUI
2866 * actually displaying the properties.
2868 * This is fixed in Win2k. admin/non-admin
2869 * connections both display changes immediately.
2871 * 14/12/01 --jerry
2874 result=update_a_printer_2(printer.info_2);
2875 break;
2877 default:
2878 result=WERR_UNKNOWN_LEVEL;
2879 break;
2882 return result;
2885 /****************************************************************************
2886 Initialize printer devmode & data with previously saved driver init values.
2887 ****************************************************************************/
2889 static BOOL set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
2891 int len = 0;
2892 pstring key;
2893 TDB_DATA kbuf, dbuf;
2894 NT_PRINTER_PARAM *current;
2895 NT_PRINTER_INFO_LEVEL_2 info;
2898 * Delete any printer data 'specifics' already set. When called for driver
2899 * replace, there will generally be some, but during an add printer, there
2900 * should not be any (if there are delete them).
2902 while ( (current=info_ptr->specific) != NULL ) {
2903 info_ptr->specific=current->next;
2904 SAFE_FREE(current->data);
2905 SAFE_FREE(current);
2908 ZERO_STRUCT(info);
2910 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
2911 dos_to_unix(key); /* Convert key to unix-codepage */
2913 kbuf.dptr = key;
2914 kbuf.dsize = strlen(key)+1;
2916 dbuf = tdb_fetch(tdb_drivers, kbuf);
2917 if (!dbuf.dptr) {
2919 * When changing to a driver that has no init info in the tdb, remove
2920 * the previous drivers init info and leave the new on blank.
2922 free_nt_devicemode(&info_ptr->devmode);
2923 return False;
2927 * Get the saved DEVMODE..
2929 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2932 * The saved DEVMODE contains the devicename from the printer used during
2933 * the initialization save. Change it to reflect the new printer.
2935 ZERO_STRUCT(info.devmode->devicename);
2936 fstrcpy(info.devmode->devicename, info_ptr->printername);
2940 * NT/2k does not change out the entire DeviceMode of a printer
2941 * when changing the driver. Only the driverextra, private, &
2942 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
2944 * Later e4xamination revealed that Windows NT/2k does reset the
2945 * the printer's device mode, bit **only** when you change a
2946 * property of the device mode such as the page orientation.
2947 * --jerry
2950 #if 1 /* JERRY */
2953 * Bind the saved DEVMODE to the new the printer.
2955 free_nt_devicemode(&info_ptr->devmode);
2956 info_ptr->devmode = info.devmode;
2957 #else
2958 /* copy the entire devmode if we currently don't have one */
2960 if (!info_ptr->devmode) {
2961 DEBUG(10,("set_driver_init_2: Current Devmode is NULL. Copying entire Device Mode\n"));
2962 info_ptr->devmode = info.devmode;
2964 else {
2965 /* only set the necessary fields */
2967 DEBUG(10,("set_driver_init_2: Setting driverversion [0x%x] and private data [0x%x]\n",
2968 info.devmode->driverversion, info.devmode->driverextra));
2970 info_ptr->devmode->driverversion = info.devmode->driverversion;
2972 SAFE_FREE(info_ptr->devmode->private);
2973 info_ptr->devmode->private = NULL;
2975 if (info.devmode->driverversion)
2976 info_ptr->devmode->private = memdup(info.devmode->private, info.devmode->driverversion);
2978 free_nt_devicemode(&info.devmode);
2980 #endif
2982 DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
2983 info_ptr->printername, info_ptr->drivername));
2986 * Add the printer data 'specifics' to the new printer
2988 len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len);
2990 SAFE_FREE(dbuf.dptr);
2992 return True;
2995 /****************************************************************************
2996 Initialize printer devmode & data with previously saved driver init values.
2997 When a printer is created using AddPrinter, the drivername bound to the
2998 printer is used to lookup previously saved driver initialization info, which
2999 is bound to the new printer.
3000 ****************************************************************************/
3002 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3004 BOOL result = False;
3006 switch (level)
3008 case 2:
3009 result = set_driver_init_2(printer->info_2);
3010 break;
3012 default:
3013 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3014 level));
3015 break;
3018 return result;
3021 /****************************************************************************
3022 Delete driver init data stored for a specified driver
3023 ****************************************************************************/
3025 BOOL del_driver_init(char *drivername)
3027 pstring key;
3028 TDB_DATA kbuf;
3030 if (!drivername || !*drivername) {
3031 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3032 return False;
3035 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3036 dos_to_unix(key); /* Convert key to unix-codepage */
3038 kbuf.dptr = key;
3039 kbuf.dsize = strlen(key)+1;
3041 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3043 return (tdb_delete(tdb_drivers, kbuf) == 0);
3046 /****************************************************************************
3047 Pack up the DEVMODE and specifics for a printer into a 'driver init' entry
3048 in the tdb. Note: this is different from the driver entry and the printer
3049 entry. There should be a single driver init entry for each driver regardless
3050 of whether it was installed from NT or 2K. Technically, they should be
3051 different, but they work out to the same struct.
3052 ****************************************************************************/
3054 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3056 pstring key;
3057 char *buf;
3058 int buflen, len, ret;
3059 TDB_DATA kbuf, dbuf;
3061 buf = NULL;
3062 buflen = 0;
3064 again:
3065 len = 0;
3066 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3068 len += pack_specifics(info->specific, buf+len, buflen-len);
3070 if (buflen != len) {
3071 char *tb;
3073 tb = (char *)Realloc(buf, len);
3074 if (!tb) {
3075 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3076 ret = -1;
3077 goto done;
3079 else buf = tb;
3080 buflen = len;
3081 goto again;
3084 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3085 dos_to_unix(key); /* Convert key to unix-codepage */
3087 kbuf.dptr = key;
3088 kbuf.dsize = strlen(key)+1;
3089 dbuf.dptr = buf;
3090 dbuf.dsize = len;
3092 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3094 done:
3095 if (ret == -1)
3096 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3098 SAFE_FREE(buf);
3100 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n",
3101 info->sharename, info->drivername));
3103 return ret;
3106 /****************************************************************************
3107 Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer
3108 ****************************************************************************/
3110 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3112 uint32 result;
3114 dump_a_printer(printer, level);
3116 switch (level)
3118 case 2:
3120 result=update_driver_init_2(printer.info_2);
3121 break;
3123 default:
3124 result=1;
3125 break;
3128 return result;
3131 /****************************************************************************
3132 Convert the printer data value, a REG_BINARY array, into an initialization
3133 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3134 got to keep the endians happy :).
3135 ****************************************************************************/
3137 static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode)
3139 BOOL result = False;
3140 prs_struct ps;
3141 DEVICEMODE devmode;
3143 ZERO_STRUCT(devmode);
3145 prs_init(&ps, 0, ctx, UNMARSHALL);
3146 ps.data_p = (char *)param->data;
3147 ps.buffer_size = param->data_len;
3149 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3150 result = convert_devicemode("", &devmode, &nt_devmode);
3151 else
3152 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3154 return result;
3157 /****************************************************************************
3158 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3160 1. Use the driver's config DLL to this UNC printername and:
3161 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3162 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3163 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3165 The last step triggers saving the "driver initialization" information for
3166 this printer into the tdb. Later, new printers that use this driver will
3167 have this initialization information bound to them. This simulates the
3168 driver initialization, as if it had run on the Samba server (as it would
3169 have done on NT).
3171 The Win32 client side code requirement sucks! But until we can run arbitrary
3172 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3174 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3175 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3176 about it and you will realize why. JRR 010720
3177 ****************************************************************************/
3179 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
3181 WERROR status = WERR_OK;
3182 TALLOC_CTX *ctx = NULL;
3183 NT_DEVICEMODE *nt_devmode = NULL;
3184 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3187 * When the DEVMODE is already set on the printer, don't try to unpack it.
3190 if (!printer->info_2->devmode && param->data_len) {
3192 * Set devmode on printer info, so entire printer initialization can be
3193 * saved to tdb.
3196 if ((ctx = talloc_init()) == NULL)
3197 return WERR_NOMEM;
3199 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3200 status = WERR_NOMEM;
3201 goto done;
3204 ZERO_STRUCTP(nt_devmode);
3207 * The DEVMODE is held in the 'data' component of the param in raw binary.
3208 * Convert it to to a devmode structure
3210 if (!convert_driver_init(param, ctx, nt_devmode)) {
3211 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3212 status = WERR_INVALID_PARAM;
3213 goto done;
3216 printer->info_2->devmode = nt_devmode;
3220 * Pack up and add (or update) the DEVMODE and any current printer data to
3221 * a 'driver init' element in the tdb
3225 if (update_driver_init(*printer, 2)!=0) {
3226 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3227 status = WERR_NOMEM;
3228 goto done;
3232 * If driver initialization info was successfully saved, set the current
3233 * printer to match it. This allows initialization of the current printer
3234 * as well as the driver.
3236 status = mod_a_printer(*printer, 2);
3237 if (!W_ERROR_IS_OK(status)) {
3238 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3239 printer->info_2->printername));
3242 #if 0 /* JERRY */
3243 srv_spoolss_sendnotify(p, handle);
3244 #endif
3246 done:
3247 talloc_destroy(ctx);
3248 if (nt_devmode)
3249 SAFE_FREE(nt_devmode->private);
3250 SAFE_FREE(nt_devmode);
3251 printer->info_2->devmode = tmp_devmode;
3253 return status;
3256 /****************************************************************************
3257 Update the driver init info (DEVMODE and specifics) for a printer
3258 ****************************************************************************/
3260 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
3262 WERROR status = WERR_OK;
3264 switch (level)
3266 case 2:
3268 status=save_driver_init_2(printer, param);
3269 break;
3271 default:
3272 status=WERR_UNKNOWN_LEVEL;
3273 break;
3276 return status;
3279 /****************************************************************************
3280 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3281 ****************************************************************************/
3283 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
3285 WERROR result;
3286 NT_PRINTER_INFO_LEVEL *printer = NULL;
3288 *pp_printer = NULL;
3290 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3292 switch (level)
3294 case 2:
3296 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3297 DEBUG(0,("get_a_printer: malloc fail.\n"));
3298 return WERR_NOMEM;
3300 ZERO_STRUCTP(printer);
3301 result=get_a_printer_2(&printer->info_2, sharename);
3302 if (W_ERROR_IS_OK(result)) {
3303 dump_a_printer(*printer, level);
3304 *pp_printer = printer;
3305 } else {
3306 SAFE_FREE(printer);
3308 break;
3310 default:
3311 result=WERR_UNKNOWN_LEVEL;
3312 break;
3315 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
3317 return result;
3320 /****************************************************************************
3321 Deletes a NT_PRINTER_INFO_LEVEL struct.
3322 ****************************************************************************/
3324 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3326 uint32 result;
3327 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3329 DEBUG(104,("freeing a printer at level [%d]\n", level));
3331 if (printer == NULL)
3332 return 0;
3334 switch (level)
3336 case 2:
3338 if (printer->info_2 != NULL)
3340 free_nt_printer_info_level_2(&printer->info_2);
3341 result=0;
3343 else
3345 result=4;
3347 break;
3349 default:
3350 result=1;
3351 break;
3354 SAFE_FREE(*pp_printer);
3355 return result;
3358 /****************************************************************************
3359 ****************************************************************************/
3360 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3362 uint32 result;
3363 DEBUG(104,("adding a printer at level [%d]\n", level));
3364 dump_a_printer_driver(driver, level);
3366 switch (level)
3368 case 3:
3370 result=add_a_printer_driver_3(driver.info_3);
3371 break;
3374 case 6:
3376 result=add_a_printer_driver_6(driver.info_6);
3377 break;
3379 default:
3380 result=1;
3381 break;
3384 return result;
3386 /****************************************************************************
3387 ****************************************************************************/
3388 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3389 fstring drivername, const fstring architecture, uint32 version)
3391 WERROR result;
3393 switch (level)
3395 case 3:
3396 /* Sometime we just want any version of the driver */
3398 if ( version == DRIVER_ANY_VERSION ) {
3399 /* look for Win2k first and then for NT4 */
3400 result = get_a_printer_driver_3(&driver->info_3, drivername,
3401 architecture, 3);
3403 if ( !W_ERROR_IS_OK(result) ) {
3404 result = get_a_printer_driver_3( &driver->info_3,
3405 drivername, architecture, 2 );
3408 else {
3409 result = get_a_printer_driver_3(&driver->info_3, drivername,
3410 architecture, version);
3412 break;
3414 default:
3415 result=W_ERROR(1);
3416 break;
3419 if (W_ERROR_IS_OK(result))
3420 dump_a_printer_driver(*driver, level);
3422 return result;
3425 /****************************************************************************
3426 ****************************************************************************/
3427 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3429 uint32 result;
3431 switch (level)
3433 case 3:
3435 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3436 if (driver.info_3 != NULL)
3438 info3=driver.info_3;
3439 SAFE_FREE(info3->dependentfiles);
3440 ZERO_STRUCTP(info3);
3441 SAFE_FREE(info3);
3442 result=0;
3444 else
3446 result=4;
3448 break;
3450 case 6:
3452 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3453 if (driver.info_6 != NULL)
3455 info6=driver.info_6;
3456 SAFE_FREE(info6->dependentfiles);
3457 SAFE_FREE(info6->previousnames);
3458 ZERO_STRUCTP(info6);
3459 SAFE_FREE(info6);
3460 result=0;
3462 else
3464 result=4;
3466 break;
3468 default:
3469 result=1;
3470 break;
3472 return result;
3476 /****************************************************************************
3477 Determine whether or not a particular driver is currently assigned
3478 to a printer
3479 ****************************************************************************/
3481 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
3483 int snum;
3484 int n_services = lp_numservices();
3485 NT_PRINTER_INFO_LEVEL *printer = NULL;
3487 if ( !info_3 )
3488 return False;
3490 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
3492 /* loop through the printers.tdb and check for the drivername */
3494 for (snum=0; snum<n_services; snum++)
3496 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
3497 continue;
3499 if ( !W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) )
3500 continue;
3502 if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
3503 free_a_printer( &printer, 2 );
3504 return True;
3507 free_a_printer( &printer, 2 );
3510 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
3512 /* report that the driver is not in use by default */
3514 return False;
3517 /****************************************************************************
3518 Remove a printer driver from the TDB. This assumes that the the driver was
3519 previously looked up.
3520 ***************************************************************************/
3522 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
3523 uint32 version, BOOL delete_files )
3525 pstring key;
3526 fstring arch;
3527 TDB_DATA kbuf, dbuf;
3528 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
3530 /* delete the tdb data first */
3532 get_short_archi(arch, info_3->environment);
3533 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
3534 arch, version, info_3->name);
3536 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
3537 key, delete_files ? "TRUE" : "FALSE" ));
3539 ctr.info_3 = info_3;
3540 dump_a_printer_driver( ctr, 3 );
3542 kbuf.dptr=key;
3543 kbuf.dsize=strlen(key)+1;
3545 /* check if the driver actually exists for this environment */
3547 dbuf = tdb_fetch( tdb_drivers, kbuf );
3548 if ( !dbuf.dptr ) {
3549 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
3550 return WERR_UNKNOWN_PRINTER_DRIVER;
3553 SAFE_FREE( dbuf.dptr );
3555 /* ok... the driver exists so the delete should return success */
3557 if (tdb_delete(tdb_drivers, kbuf) == -1) {
3558 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
3559 return WERR_ACCESS_DENIED;
3562 #if 0 /* JERRY - no used in Samba 2.2.x */
3564 * now delete any associated files if delete_files == True
3565 * even if this part failes, we return succes because the
3566 * driver doesn not exist any more
3569 if ( delete_files )
3570 delete_driver_files( i, user );
3572 #endif
3574 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
3576 return WERR_OK;
3579 /****************************************************************************
3580 ****************************************************************************/
3581 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
3582 fstring value, uint8 **data, uint32 *type, uint32 *len)
3584 /* right now that's enough ! */
3585 NT_PRINTER_PARAM *param;
3586 int i=0;
3588 param=printer.info_2->specific;
3590 while (param != NULL && i < param_index) {
3591 param=param->next;
3592 i++;
3595 if (param == NULL)
3596 return False;
3598 /* exited because it exist */
3599 *type=param->type;
3600 StrnCpy(value, param->value, sizeof(fstring)-1);
3601 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3602 if(*data == NULL)
3603 return False;
3604 ZERO_STRUCTP(*data);
3605 memcpy(*data, param->data, param->data_len);
3606 *len=param->data_len;
3607 return True;
3610 /****************************************************************************
3611 ****************************************************************************/
3612 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
3613 fstring value, uint8 **data, uint32 *type, uint32 *len)
3615 /* right now that's enough ! */
3616 NT_PRINTER_PARAM *param;
3618 DEBUG(10, ("get_specific_param\n"));
3620 param=printer.info_2->specific;
3622 while (param != NULL)
3624 #if 1 /* JRA - I think this should be case insensitive.... */
3625 if ( strequal(value, param->value)
3626 #else
3627 if ( !strcmp(value, param->value)
3628 #endif
3629 && strlen(value)==strlen(param->value))
3630 break;
3632 param=param->next;
3635 if (param != NULL)
3637 DEBUGADD(10, ("get_specific_param: found one param\n"));
3638 /* exited because it exist */
3639 *type=param->type;
3641 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3642 if(*data == NULL)
3643 return False;
3644 memcpy(*data, param->data, param->data_len);
3645 *len=param->data_len;
3647 DEBUGADD(10, ("get_specific_param: exit true\n"));
3648 return (True);
3650 DEBUGADD(10, ("get_specific_param: exit false\n"));
3651 return (False);
3654 /****************************************************************************
3655 Store a security desc for a printer.
3656 ****************************************************************************/
3658 WERROR nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
3660 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3661 SEC_DESC_BUF *old_secdesc_ctr = NULL;
3662 prs_struct ps;
3663 TALLOC_CTX *mem_ctx = NULL;
3664 fstring key;
3665 WERROR status;
3667 mem_ctx = talloc_init();
3668 if (mem_ctx == NULL)
3669 return WERR_NOMEM;
3671 /* The old owner and group sids of the security descriptor are not
3672 present when new ACEs are added or removed by changing printer
3673 permissions through NT. If they are NULL in the new security
3674 descriptor then copy them over from the old one. */
3676 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3677 DOM_SID *owner_sid, *group_sid;
3678 SEC_ACL *dacl, *sacl;
3679 SEC_DESC *psd = NULL;
3680 size_t size;
3682 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3684 /* Pick out correct owner and group sids */
3686 owner_sid = secdesc_ctr->sec->owner_sid ?
3687 secdesc_ctr->sec->owner_sid :
3688 old_secdesc_ctr->sec->owner_sid;
3690 group_sid = secdesc_ctr->sec->grp_sid ?
3691 secdesc_ctr->sec->grp_sid :
3692 old_secdesc_ctr->sec->grp_sid;
3694 dacl = secdesc_ctr->sec->dacl ?
3695 secdesc_ctr->sec->dacl :
3696 old_secdesc_ctr->sec->dacl;
3698 sacl = secdesc_ctr->sec->sacl ?
3699 secdesc_ctr->sec->sacl :
3700 old_secdesc_ctr->sec->sacl;
3702 /* Make a deep copy of the security descriptor */
3704 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3705 owner_sid, group_sid,
3706 sacl,
3707 dacl,
3708 &size);
3710 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3713 if (!new_secdesc_ctr) {
3714 new_secdesc_ctr = secdesc_ctr;
3717 /* Store the security descriptor in a tdb */
3719 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3720 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3722 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3723 &ps, 1)) {
3724 status = WERR_BADFUNC;
3725 goto out;
3728 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3730 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
3731 status = WERR_OK;
3732 } else {
3733 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3734 status = WERR_BADFUNC;
3737 /* Free malloc'ed memory */
3739 out:
3741 prs_mem_free(&ps);
3742 if (mem_ctx)
3743 talloc_destroy(mem_ctx);
3744 return status;
3747 /****************************************************************************
3748 Construct a default security descriptor buffer for a printer.
3749 ****************************************************************************/
3751 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3753 extern DOM_SID global_sam_sid;
3754 SEC_ACE ace[3];
3755 SEC_ACCESS sa;
3756 SEC_ACL *psa = NULL;
3757 SEC_DESC_BUF *sdb = NULL;
3758 SEC_DESC *psd = NULL;
3759 DOM_SID owner_sid;
3760 size_t sd_size;
3761 enum SID_NAME_USE name_type;
3762 fstring dos_domain;
3764 /* Create an ACE where Everyone is allowed to print */
3766 init_sec_access(&sa, PRINTER_ACE_PRINT);
3767 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3768 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3770 /* Make the security descriptor owned by the Administrators group
3771 on the PDC of the domain. */
3773 /* Note that for hysterical raisins, the argument to
3774 secrets_fetch_domain_sid() must be in dos codepage format.
3775 Aargh! */
3777 fstrcpy(dos_domain, lp_workgroup());
3778 unix_to_dos(dos_domain);
3780 if (secrets_fetch_domain_sid(dos_domain, &owner_sid)) {
3781 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3782 } else {
3784 /* Backup plan - make printer owned by admins or root.
3785 This should emulate a lanman printer as security
3786 settings can't be changed. */
3788 if (!lookup_name("root", &owner_sid, &name_type)) {
3789 sid_copy(&owner_sid, &global_sam_sid);
3790 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3794 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3795 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3796 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
3797 SEC_ACE_FLAG_INHERIT_ONLY);
3799 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3800 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3801 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3803 /* The ACL revision number in rpc_secdesc.h differs from the one
3804 created by NT when setting ACE entries in printer
3805 descriptors. NT4 complains about the property being edited by a
3806 NT5 machine. */
3808 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
3809 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
3810 &owner_sid, NULL,
3811 NULL, psa, &sd_size);
3814 if (!psd) {
3815 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
3816 return NULL;
3819 sdb = make_sec_desc_buf(ctx, sd_size, psd);
3821 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
3822 (unsigned int)sd_size));
3824 return sdb;
3827 /****************************************************************************
3828 Get a security desc for a printer.
3829 ****************************************************************************/
3831 BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
3833 prs_struct ps;
3834 fstring key;
3835 char *temp;
3837 if ((temp = strchr(printername + 2, '\\'))) {
3838 printername = temp + 1;
3841 /* Fetch security descriptor from tdb */
3843 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3845 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
3846 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
3848 DEBUG(4,("using default secdesc for %s\n", printername));
3850 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
3851 return False;
3854 /* Save default security descriptor for later */
3856 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
3857 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
3859 if (sec_io_desc_buf("nt_printing_setsec", secdesc_ctr, &ps, 1))
3860 tdb_prs_store(tdb_printers, key, &ps);
3862 prs_mem_free(&ps);
3864 return True;
3867 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
3868 this security descriptor has been created when winbindd was
3869 down. Take ownership of security descriptor. */
3871 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
3872 DOM_SID owner_sid;
3873 enum SID_NAME_USE name_type;
3875 /* Change sd owner to workgroup administrator */
3877 if (winbind_lookup_name(NULL, lp_workgroup(), &owner_sid,
3878 &name_type)) {
3879 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3880 SEC_DESC *psd = NULL;
3881 size_t size;
3883 /* Create new sd */
3885 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3887 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
3888 &owner_sid,
3889 (*secdesc_ctr)->sec->grp_sid,
3890 (*secdesc_ctr)->sec->sacl,
3891 (*secdesc_ctr)->sec->dacl,
3892 &size);
3894 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
3896 /* Swap with other one */
3898 *secdesc_ctr = new_secdesc_ctr;
3900 /* Set it */
3902 nt_printing_setsec(printername, *secdesc_ctr);
3906 if (DEBUGLEVEL >= 10) {
3907 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
3908 int i;
3910 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3911 printername, the_acl->num_aces));
3913 for (i = 0; i < the_acl->num_aces; i++) {
3914 fstring sid_str;
3916 sid_to_string(sid_str, &the_acl->ace[i].trustee);
3918 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
3919 the_acl->ace[i].type, the_acl->ace[i].flags,
3920 the_acl->ace[i].info.mask));
3924 prs_mem_free(&ps);
3925 return True;
3928 /* error code:
3929 0: everything OK
3930 1: level not implemented
3931 2: file doesn't exist
3932 3: can't allocate memory
3933 4: can't free memory
3934 5: non existant struct
3938 A printer and a printer driver are 2 different things.
3939 NT manages them separatelly, Samba does the same.
3940 Why ? Simply because it's easier and it makes sense !
3942 Now explanation: You have 3 printers behind your samba server,
3943 2 of them are the same make and model (laser A and B). But laser B
3944 has an 3000 sheet feeder and laser A doesn't such an option.
3945 Your third printer is an old dot-matrix model for the accounting :-).
3947 If the /usr/local/samba/lib directory (default dir), you will have
3948 5 files to describe all of this.
3950 3 files for the printers (1 by printer):
3951 NTprinter_laser A
3952 NTprinter_laser B
3953 NTprinter_accounting
3954 2 files for the drivers (1 for the laser and 1 for the dot matrix)
3955 NTdriver_printer model X
3956 NTdriver_printer model Y
3958 jfm: I should use this comment for the text file to explain
3959 same thing for the forms BTW.
3960 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
3964 /* Convert generic access rights to printer object specific access rights.
3965 It turns out that NT4 security descriptors use generic access rights and
3966 NT5 the object specific ones. */
3968 void map_printer_permissions(SEC_DESC *sd)
3970 int i;
3972 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
3973 se_map_generic(&sd->dacl->ace[i].info.mask,
3974 &printer_generic_mapping);
3978 /****************************************************************************
3979 Check a user has permissions to perform the given operation. We use the
3980 permission constants defined in include/rpc_spoolss.h to check the various
3981 actions we perform when checking printer access.
3983 PRINTER_ACCESS_ADMINISTER:
3984 print_queue_pause, print_queue_resume, update_printer_sec,
3985 update_printer, spoolss_addprinterex_level_2,
3986 _spoolss_setprinterdata
3988 PRINTER_ACCESS_USE:
3989 print_job_start
3991 JOB_ACCESS_ADMINISTER:
3992 print_job_delete, print_job_pause, print_job_resume,
3993 print_queue_purge
3995 ****************************************************************************/
3996 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3998 SEC_DESC_BUF *secdesc = NULL;
3999 uint32 access_granted;
4000 NTSTATUS status;
4001 BOOL result;
4002 char *pname;
4003 TALLOC_CTX *mem_ctx = NULL;
4004 extern struct current_user current_user;
4006 /* If user is NULL then use the current_user structure */
4008 if (!user)
4009 user = &current_user;
4011 /* Always allow root or printer admins to do anything */
4013 if (user->uid == 0 ||
4014 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
4015 return True;
4018 /* Get printer name */
4020 pname = PRINTERNAME(snum);
4022 if (!pname || !*pname) {
4023 errno = EACCES;
4024 return False;
4027 /* Get printer security descriptor */
4029 if(!(mem_ctx = talloc_init())) {
4030 errno = ENOMEM;
4031 return False;
4034 nt_printing_getsec(mem_ctx, pname, &secdesc);
4036 if (access_type == JOB_ACCESS_ADMINISTER) {
4037 SEC_DESC_BUF *parent_secdesc = secdesc;
4039 /* Create a child security descriptor to check permissions
4040 against. This is because print jobs are child objects
4041 objects of a printer. */
4043 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4045 /* Now this is the bit that really confuses me. The access
4046 type needs to be changed from JOB_ACCESS_ADMINISTER to
4047 PRINTER_ACCESS_ADMINISTER for this to work. Something
4048 to do with the child (job) object becoming like a
4049 printer?? -tpot */
4051 access_type = PRINTER_ACCESS_ADMINISTER;
4054 /* Check access */
4056 map_printer_permissions(secdesc->sec);
4058 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4059 &access_granted, &status);
4061 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4063 talloc_destroy(mem_ctx);
4065 if (!result)
4066 errno = EACCES;
4068 return result;
4071 /****************************************************************************
4072 Check the time parameters allow a print operation.
4073 *****************************************************************************/
4075 BOOL print_time_access_check(int snum)
4077 NT_PRINTER_INFO_LEVEL *printer = NULL;
4078 BOOL ok = False;
4079 time_t now = time(NULL);
4080 struct tm *t;
4081 uint32 mins;
4083 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4084 return False;
4086 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
4087 ok = True;
4089 t = gmtime(&now);
4090 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4092 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
4093 ok = True;
4095 free_a_printer(&printer, 2);
4097 if (!ok)
4098 errno = EACCES;
4100 return ok;
4103 #if 0 /* JERRY - not used */
4104 /****************************************************************************
4105 Attempt to write a default device.
4106 *****************************************************************************/
4108 WERROR printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
4110 NT_PRINTER_INFO_LEVEL *printer = NULL;
4111 WERROR result;
4114 * Don't bother if no default devicemode was sent.
4117 if (printer_default->devmode_cont.devmode == NULL)
4118 return WERR_OK;
4120 result = get_a_printer(&printer, 2, lp_servicename(snum));
4121 if (!W_ERROR_IS_OK(result)) return result;
4124 * Just ignore it if we already have a devmode.
4126 #if 0
4127 if (printer->info_2->devmode != NULL)
4128 goto done;
4129 #endif
4131 * We don't have a devicemode and we're trying to write
4132 * one. Check we have the access needed.
4134 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
4136 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
4137 PRINTER_ACCESS_ADMINISTER) {
4138 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
4139 result = WERR_ACCESS_DENIED;
4140 goto done;
4143 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4144 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
4145 lp_servicename(snum) ));
4146 result = WERR_ACCESS_DENIED;
4147 /*result = NT_STATUS_NO_PROBLEMO;*/
4148 goto done;
4151 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
4154 * Convert the on the wire devicemode format to the internal one.
4157 if (!convert_devicemode(printer->info_2->printername,
4158 printer_default->devmode_cont.devmode,
4159 &printer->info_2->devmode)) {
4160 result = WERR_NOMEM;
4161 goto done;
4165 * Finally write back to the tdb.
4168 result = mod_a_printer(*printer, 2);
4170 done:
4172 free_a_printer(&printer, 2);
4173 return result;
4175 #endif /* JERRY */