2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
6 * Copyright (C) Gerald Carter 2002.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 extern DOM_SID global_sid_World;
27 static TDB_CONTEXT *tdb_forms; /* used for forms files */
28 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29 static TDB_CONTEXT *tdb_printers; /* used for printers files */
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
42 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
44 /* Map generic permissions to printer object specific permissions */
46 GENERIC_MAPPING printer_generic_mapping = {
53 STANDARD_MAPPING printer_std_mapping = {
60 /* Map generic permissions to print server object specific permissions */
62 GENERIC_MAPPING printserver_generic_mapping = {
69 STANDARD_MAPPING printserver_std_mapping = {
76 /* We need one default form to support our default printer. Msoft adds the
77 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
78 array index). Letter is always first, so (for the current code) additions
79 always put things in the correct order. */
80 static nt_forms_struct default_forms[] = {
81 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
84 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
85 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
86 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
87 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
88 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
89 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
92 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
93 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
94 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
95 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
96 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
97 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
98 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
99 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
100 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
101 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
102 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
103 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
104 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
105 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
106 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
107 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
108 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
109 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
110 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
111 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
112 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
113 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
114 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
115 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
116 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
117 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
118 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
119 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
120 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
121 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
122 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
123 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
124 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
125 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
126 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
127 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
128 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
131 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
132 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
133 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
134 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
135 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
136 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
138 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
139 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
140 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
141 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
142 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
143 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
144 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
145 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
146 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
147 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
148 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
149 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
150 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
151 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
152 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
153 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
154 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
155 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
156 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
157 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
158 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
159 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
160 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
161 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
162 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
163 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
164 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
165 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
166 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
167 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
168 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
169 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
170 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
171 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
172 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
173 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
174 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
175 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
176 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
177 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
178 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
179 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
180 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
181 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
182 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
183 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
184 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
185 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
186 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
187 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
188 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
189 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
190 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
191 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
192 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
193 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
194 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
195 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
196 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
197 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
198 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
201 static BOOL upgrade_to_version_3(void)
203 TDB_DATA kbuf, newkey, dbuf;
205 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
207 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
208 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
210 dbuf = tdb_fetch(tdb_drivers, kbuf);
212 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
213 DEBUG(0,("upgrade_to_version_3:moving form\n"));
214 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
215 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
218 if (tdb_delete(tdb_drivers, kbuf) != 0) {
219 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
224 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
225 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
226 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
227 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
230 if (tdb_delete(tdb_drivers, kbuf) != 0) {
231 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
236 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
237 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
238 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
239 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
242 if (tdb_delete(tdb_drivers, kbuf) != 0) {
243 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
248 SAFE_FREE(dbuf.dptr);
254 /****************************************************************************
255 Open the NT printing tdb.
256 ****************************************************************************/
258 BOOL nt_printing_init(void)
260 static pid_t local_pid;
261 char *vstring = "INFO/version";
263 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
266 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
268 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
269 lock_path("ntdrivers.tdb"), strerror(errno) ));
273 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
275 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
276 lock_path("ntprinters.tdb"), strerror(errno) ));
280 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
282 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
283 lock_path("ntforms.tdb"), strerror(errno) ));
287 local_pid = sys_getpid();
289 /* handle a Samba upgrade */
290 tdb_lock_bystring(tdb_drivers, vstring);
294 /* Cope with byte-reversed older versions of the db. */
295 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
296 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
297 /* Written on a bigendian machine with old fetch_int code. Save as le. */
298 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
299 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
300 vers_id = NTDRIVERS_DATABASE_VERSION;
303 if (vers_id != NTDRIVERS_DATABASE_VERSION) {
305 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
306 if (!upgrade_to_version_3())
309 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
311 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
314 tdb_unlock_bystring(tdb_drivers, vstring);
316 update_c_setprinter(True);
319 * register callback to handle updating printers as new
320 * drivers are installed
323 message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
326 * register callback to handle updating printer data
327 * when a driver is initialized
330 message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
336 /*******************************************************************
337 tdb traversal function for counting printers.
338 ********************************************************************/
340 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
341 TDB_DATA data, void *context)
343 int *printer_count = (int*)context;
345 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
347 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
353 /*******************************************************************
354 Update the spooler global c_setprinter. This variable is initialized
355 when the parent smbd starts with the number of existing printers. It
356 is monotonically increased by the current number of printers *after*
357 each add or delete printer RPC. Only Microsoft knows why... JRR020119
358 ********************************************************************/
360 uint32 update_c_setprinter(BOOL initialize)
363 int32 printer_count = 0;
365 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
367 /* Traverse the tdb, counting the printers */
368 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
370 /* If initializing, set c_setprinter to current printers count
371 * otherwise, bump it by the current printer count
374 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
376 c_setprinter = printer_count;
378 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
379 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
381 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
383 return (uint32)c_setprinter;
386 /*******************************************************************
387 Get the spooler global c_setprinter, accounting for initialization.
388 ********************************************************************/
390 uint32 get_c_setprinter(void)
392 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
394 if (c_setprinter == (int32)-1)
395 c_setprinter = update_c_setprinter(True);
397 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
399 return (uint32)c_setprinter;
402 /****************************************************************************
403 Get builtin form struct list.
404 ****************************************************************************/
406 int get_builtin_ntforms(nt_forms_struct **list)
408 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
409 return sizeof(default_forms) / sizeof(default_forms[0]);
412 /****************************************************************************
413 get a builtin form struct
414 ****************************************************************************/
416 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
420 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
421 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
422 count = sizeof(default_forms) / sizeof(default_forms[0]);
423 for (i=0;i<count;i++) {
424 if (strequal(form_name,default_forms[i].name)) {
425 DEBUGADD(6,("Found builtin form %s \n", form_name));
426 memcpy(form,&default_forms[i],sizeof(*form));
434 /****************************************************************************
435 get a form struct list
436 ****************************************************************************/
437 int get_ntforms(nt_forms_struct **list)
439 TDB_DATA kbuf, newkey, dbuf;
441 nt_forms_struct form;
446 for (kbuf = tdb_firstkey(tdb_forms);
448 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
450 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
453 dbuf = tdb_fetch(tdb_forms, kbuf);
457 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
458 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
459 &i, &form.flag, &form.width, &form.length, &form.left,
460 &form.top, &form.right, &form.bottom);
461 SAFE_FREE(dbuf.dptr);
462 if (ret != dbuf.dsize)
465 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
467 DEBUG(0,("get_ntforms: Realloc fail.\n"));
479 /****************************************************************************
480 write a form struct list
481 ****************************************************************************/
482 int write_ntforms(nt_forms_struct **list, int number)
489 for (i=0;i<number;i++) {
490 /* save index, so list is rebuilt in correct order */
491 len = tdb_pack(buf, sizeof(buf), "dddddddd",
492 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
493 (*list)[i].left, (*list)[i].top, (*list)[i].right,
495 if (len > sizeof(buf)) break;
496 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
497 kbuf.dsize = strlen(key)+1;
501 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
507 /****************************************************************************
508 add a form struct at the end of the list
509 ****************************************************************************/
510 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
518 * NT tries to add forms even when
519 * they are already in the base
520 * only update the values if already present
525 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
526 for (n=0; n<*count; n++) {
527 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
528 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
535 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
536 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
540 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
544 (*list)[n].flag=form->flags;
545 (*list)[n].width=form->size_x;
546 (*list)[n].length=form->size_y;
547 (*list)[n].left=form->left;
548 (*list)[n].top=form->top;
549 (*list)[n].right=form->right;
550 (*list)[n].bottom=form->bottom;
555 /****************************************************************************
556 delete a named form struct
557 ****************************************************************************/
558 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
567 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
569 for (n=0; n<*count; n++) {
570 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
571 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
577 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
578 *ret = WERR_INVALID_PARAM;
582 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
583 kbuf.dsize = strlen(key)+1;
585 if (tdb_delete(tdb_forms, kbuf) != 0) {
593 /****************************************************************************
595 ****************************************************************************/
596 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
600 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
602 DEBUG(106, ("[%s]\n", form_name));
603 for (n=0; n<count; n++)
605 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
606 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
610 if (n==count) return;
612 (*list)[n].flag=form->flags;
613 (*list)[n].width=form->size_x;
614 (*list)[n].length=form->size_y;
615 (*list)[n].left=form->left;
616 (*list)[n].top=form->top;
617 (*list)[n].right=form->right;
618 (*list)[n].bottom=form->bottom;
621 /****************************************************************************
622 get the nt drivers list
624 traverse the database and look-up the matching names
625 ****************************************************************************/
626 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
632 TDB_DATA kbuf, newkey;
634 get_short_archi(short_archi, architecture);
635 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
637 for (kbuf = tdb_firstkey(tdb_drivers);
639 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
640 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
642 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
643 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
648 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
655 /****************************************************************************
656 function to do the mapping between the long architecture name and
658 ****************************************************************************/
659 BOOL get_short_archi(char *short_archi, char *long_archi)
666 struct table archi_table[]=
668 {"Windows 4.0", "WIN40" },
669 {"Windows NT x86", "W32X86" },
670 {"Windows NT R4000", "W32MIPS" },
671 {"Windows NT Alpha_AXP", "W32ALPHA" },
672 {"Windows NT PowerPC", "W32PPC" },
678 DEBUG(107,("Getting architecture dependant directory\n"));
681 } while ( (archi_table[i].long_archi!=NULL ) &&
682 StrCaseCmp(long_archi, archi_table[i].long_archi) );
684 if (archi_table[i].long_archi==NULL) {
685 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
689 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
691 DEBUGADD(108,("index: [%d]\n", i));
692 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
693 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
698 /****************************************************************************
699 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
700 There are two case to be covered here: PE (Portable Executable) and NE (New
701 Executable) files. Both files support the same INFO structure, but PE files
702 store the signature in unicode, and NE files store it as !unicode.
703 returns -1 on error, 1 on version info found, and 0 on no version info found.
704 ****************************************************************************/
706 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
712 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
713 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
714 fname, PE_HEADER_SIZE));
718 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
719 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
720 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
722 goto no_version_info;
725 /* Is this really a DOS header? */
726 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
727 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
728 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
729 goto no_version_info;
732 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
733 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
734 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
736 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
737 goto no_version_info;
740 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
741 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
743 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
744 goto no_version_info;
747 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
748 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
750 int section_table_bytes;
752 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
753 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
754 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
755 /* At this point, we assume the file is in error. It still could be somthing
756 * else besides a PE file, but it unlikely at this point.
761 /* get the section table */
762 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
763 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
765 if ((buf=malloc(section_table_bytes)) == NULL) {
766 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
767 fname, section_table_bytes));
771 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
772 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
777 /* Iterate the section table looking for the resource section ".rsrc" */
778 for (i = 0; i < num_sections; i++) {
779 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
781 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
782 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
783 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
786 if ((buf=malloc(section_bytes)) == NULL) {
787 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
788 fname, section_bytes));
792 /* Seek to the start of the .rsrc section info */
793 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
794 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
799 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
800 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
805 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
806 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
807 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
808 /* Align to next long address */
809 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
811 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
812 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
813 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
815 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
816 fname, *major, *minor,
817 (*major>>16)&0xffff, *major&0xffff,
818 (*minor>>16)&0xffff, *minor&0xffff));
827 /* Version info not found, fall back to origin date/time */
828 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
832 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
833 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
834 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
835 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
836 /* At this point, we assume the file is in error. It still could be somthing
837 * else besides a NE file, but it unlikely at this point. */
841 /* Allocate a bit more space to speed up things */
843 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
844 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
845 fname, PE_HEADER_SIZE));
849 /* This is a HACK! I got tired of trying to sort through the messy
850 * 'NE' file format. If anyone wants to clean this up please have at
851 * it, but this works. 'NE' files will eventually fade away. JRR */
852 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
853 /* Cover case that should not occur in a well formed 'NE' .dll file */
854 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
856 for(i=0; i<byte_count; i++) {
857 /* Fast skip past data that can't possibly match */
858 if (buf[i] != 'V') continue;
860 /* Potential match data crosses buf boundry, move it to beginning
861 * of buf, and fill the buf with as much as it will hold. */
862 if (i>byte_count-VS_VERSION_INFO_SIZE) {
865 memcpy(buf, &buf[i], byte_count-i);
866 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
867 (byte_count-i))) < 0) {
869 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
874 byte_count = bc + (byte_count - i);
875 if (byte_count<VS_VERSION_INFO_SIZE) break;
880 /* Check that the full signature string and the magic number that
881 * follows exist (not a perfect solution, but the chances that this
882 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
883 * twice, as it is simpler to read the code. */
884 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
885 /* Compute skip alignment to next long address */
886 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
887 sizeof(VS_SIGNATURE)) & 3;
888 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
890 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
891 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
892 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
893 fname, *major, *minor,
894 (*major>>16)&0xffff, *major&0xffff,
895 (*minor>>16)&0xffff, *minor&0xffff));
902 /* Version info not found, fall back to origin date/time */
903 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
908 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
909 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
910 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
921 /****************************************************************************
922 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
923 share one or more files. During the MS installation process files are checked
924 to insure that only a newer version of a shared file is installed over an
925 older version. There are several possibilities for this comparison. If there
926 is no previous version, the new one is newer (obviously). If either file is
927 missing the version info structure, compare the creation date (on Unix use
928 the modification date). Otherwise chose the numerically larger version number.
929 ****************************************************************************/
930 static int file_version_is_newer(connection_struct *conn, fstring new_file,
933 BOOL use_version = True;
938 time_t new_create_time;
942 time_t old_create_time;
946 files_struct *fsp = NULL;
948 SMB_STRUCT_STAT stat_buf;
952 ZERO_STRUCT(stat_buf);
953 new_create_time = (time_t)0;
954 old_create_time = (time_t)0;
956 /* Get file version info (if available) for previous file (if it exists) */
957 pstrcpy(filepath, old_file);
959 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
961 fsp = open_file_shared(conn, filepath, &stat_buf,
962 SET_OPEN_MODE(DOS_OPEN_RDONLY),
963 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
964 0, 0, &access_mode, &action);
966 /* Old file not found, so by definition new file is in fact newer */
967 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
972 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
973 if (ret == -1) goto error_exit;
976 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
979 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
980 old_create_time = st.st_mtime;
981 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
984 close_file(fsp, True);
986 /* Get file version info (if available) for new file */
987 pstrcpy(filepath, new_file);
988 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
990 fsp = open_file_shared(conn, filepath, &stat_buf,
991 SET_OPEN_MODE(DOS_OPEN_RDONLY),
992 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
993 0, 0, &access_mode, &action);
995 /* New file not found, this shouldn't occur if the caller did its job */
996 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1001 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1002 if (ret == -1) goto error_exit;
1005 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1007 use_version = False;
1008 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1009 new_create_time = st.st_mtime;
1010 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1013 close_file(fsp, True);
1015 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1016 /* Compare versions and choose the larger version number */
1017 if (new_major > old_major ||
1018 (new_major == old_major && new_minor > old_minor)) {
1020 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1024 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1029 /* Compare modification time/dates and choose the newest time/date */
1030 if (new_create_time > old_create_time) {
1031 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1035 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1042 close_file(fsp, True);
1046 /****************************************************************************
1047 Determine the correct cVersion associated with an architecture and driver
1048 ****************************************************************************/
1049 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
1050 struct current_user *user, WERROR *perr)
1058 files_struct *fsp = NULL;
1061 connection_struct *conn;
1065 *perr = WERR_INVALID_PARAM;
1067 /* If architecture is Windows 95/98/ME, the version is always 0. */
1068 if (strcmp(architecture, "WIN40") == 0) {
1069 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1075 * Connect to the print$ share under the same account as the user connected
1076 * to the rpc pipe. Note we must still be root to do this.
1079 /* Null password is ok - we are already an authenticated user... */
1080 null_pw = data_blob(NULL, 0);
1082 conn = make_connection_with_chdir("print$", null_pw, "A:", user->vuid, &nt_status);
1086 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1087 *perr = ntstatus_to_werror(nt_status);
1091 /* We are temporarily becoming the connection user. */
1092 if (!become_user(conn, conn->vuid)) {
1093 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1094 *perr = WERR_ACCESS_DENIED;
1098 /* Open the driver file (Portable Executable format) and determine the
1099 * deriver the cversion. */
1100 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1102 unix_convert(driverpath,conn,NULL,&bad_path,&st);
1104 fsp = open_file_shared(conn, driverpath, &st,
1105 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1106 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1107 0, 0, &access_mode, &action);
1109 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1110 driverpath, errno));
1111 *perr = WERR_ACCESS_DENIED;
1117 int ret = get_file_version(fsp, driverpath, &major, &minor);
1118 if (ret == -1) goto error_exit;
1121 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1126 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1127 * for more details. Version in this case is not just the version of the
1128 * file, but the version in the sense of kernal mode (2) vs. user mode
1129 * (3) drivers. Other bits of the version fields are the version info.
1132 cversion = major & 0x0000ffff;
1134 case 2: /* WinNT drivers */
1135 case 3: /* Win2K drivers */
1139 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1140 driverpath, cversion));
1144 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1145 driverpath, major, minor));
1148 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1149 driverpath, cversion));
1151 close_file(fsp, True);
1152 close_cnum(conn, user->vuid);
1161 close_file(fsp, True);
1163 close_cnum(conn, user->vuid);
1168 /****************************************************************************
1169 ****************************************************************************/
1170 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1171 struct current_user *user)
1173 fstring architecture;
1179 /* clean up the driver name.
1180 * we can get .\driver.dll
1181 * or worse c:\windows\system\driver.dll !
1183 /* using an intermediate string to not have overlaping memcpy()'s */
1184 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1185 fstrcpy(new_name, p+1);
1186 fstrcpy(driver->driverpath, new_name);
1189 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1190 fstrcpy(new_name, p+1);
1191 fstrcpy(driver->datafile, new_name);
1194 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1195 fstrcpy(new_name, p+1);
1196 fstrcpy(driver->configfile, new_name);
1199 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1200 fstrcpy(new_name, p+1);
1201 fstrcpy(driver->helpfile, new_name);
1204 if (driver->dependentfiles) {
1205 for (i=0; *driver->dependentfiles[i]; i++) {
1206 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1207 fstrcpy(new_name, p+1);
1208 fstrcpy(driver->dependentfiles[i], new_name);
1213 get_short_archi(architecture, driver->environment);
1215 /* jfm:7/16/2000 the client always sends the cversion=0.
1216 * The server should check which version the driver is by reading
1217 * the PE header of driver->driverpath.
1219 * For Windows 95/98 the version is 0 (so the value sent is correct)
1220 * For Windows NT (the architecture doesn't matter)
1221 * NT 3.1: cversion=0
1222 * NT 3.5/3.51: cversion=1
1226 if ((driver->cversion = get_correct_cversion( architecture,
1227 driver->driverpath, user, &err)) == -1)
1233 /****************************************************************************
1234 ****************************************************************************/
1235 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1237 fstring architecture;
1243 /* clean up the driver name.
1244 * we can get .\driver.dll
1245 * or worse c:\windows\system\driver.dll !
1247 /* using an intermediate string to not have overlaping memcpy()'s */
1248 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1249 fstrcpy(new_name, p+1);
1250 fstrcpy(driver->driverpath, new_name);
1253 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1254 fstrcpy(new_name, p+1);
1255 fstrcpy(driver->datafile, new_name);
1258 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1259 fstrcpy(new_name, p+1);
1260 fstrcpy(driver->configfile, new_name);
1263 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1264 fstrcpy(new_name, p+1);
1265 fstrcpy(driver->helpfile, new_name);
1268 if (driver->dependentfiles) {
1269 for (i=0; *driver->dependentfiles[i]; i++) {
1270 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1271 fstrcpy(new_name, p+1);
1272 fstrcpy(driver->dependentfiles[i], new_name);
1277 get_short_archi(architecture, driver->environment);
1279 /* jfm:7/16/2000 the client always sends the cversion=0.
1280 * The server should check which version the driver is by reading
1281 * the PE header of driver->driverpath.
1283 * For Windows 95/98 the version is 0 (so the value sent is correct)
1284 * For Windows NT (the architecture doesn't matter)
1285 * NT 3.1: cversion=0
1286 * NT 3.5/3.51: cversion=1
1290 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1296 /****************************************************************************
1297 ****************************************************************************/
1298 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1299 uint32 level, struct current_user *user)
1304 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1305 driver=driver_abstract.info_3;
1306 return clean_up_driver_struct_level_3(driver, user);
1310 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1311 driver=driver_abstract.info_6;
1312 return clean_up_driver_struct_level_6(driver, user);
1315 return WERR_INVALID_PARAM;
1319 /****************************************************************************
1320 This function sucks and should be replaced. JRA.
1321 ****************************************************************************/
1323 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1325 dst->cversion = src->version;
1327 fstrcpy( dst->name, src->name);
1328 fstrcpy( dst->environment, src->environment);
1329 fstrcpy( dst->driverpath, src->driverpath);
1330 fstrcpy( dst->datafile, src->datafile);
1331 fstrcpy( dst->configfile, src->configfile);
1332 fstrcpy( dst->helpfile, src->helpfile);
1333 fstrcpy( dst->monitorname, src->monitorname);
1334 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1335 dst->dependentfiles = src->dependentfiles;
1338 #if 0 /* Debugging function */
1340 static char* ffmt(unsigned char *c){
1342 static char ffmt_str[17];
1344 for (i=0; i<16; i++) {
1345 if ((c[i] < ' ') || (c[i] > '~'))
1356 /****************************************************************************
1357 ****************************************************************************/
1358 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1359 struct current_user *user, WERROR *perr)
1361 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1362 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1363 fstring architecture;
1368 connection_struct *conn;
1375 memset(inbuf, '\0', sizeof(inbuf));
1376 memset(outbuf, '\0', sizeof(outbuf));
1380 driver=driver_abstract.info_3;
1381 else if (level==6) {
1382 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1383 driver = &converted_driver;
1385 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1389 get_short_archi(architecture, driver->environment);
1392 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1393 * Note we must be root to do this.
1397 null_pw = data_blob(NULL, 0);
1398 conn = make_connection_with_chdir("print$", null_pw, "A:", user->vuid, &nt_status);
1402 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1403 *perr = ntstatus_to_werror(nt_status);
1408 * Save who we are - we are temporarily becoming the connection user.
1411 if (!become_user(conn, conn->vuid)) {
1412 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1417 * make the directories version and version\driver_name
1418 * under the architecture directory.
1420 DEBUG(5,("Creating first directory\n"));
1421 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1422 mkdir_internal(conn, new_dir);
1424 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1425 * listed for this driver which has already been moved, skip it (note:
1426 * drivers may list the same file name several times. Then check if the
1427 * file already exists in archi\cversion\, if so, check that the version
1428 * info (or time stamps if version info is unavailable) is newer (or the
1429 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1430 * Otherwise, delete the file.
1432 * If a file is not moved to archi\cversion\ because of an error, all the
1433 * rest of the 'unmoved' driver files are removed from archi\. If one or
1434 * more of the driver's files was already moved to archi\cversion\, it
1435 * potentially leaves the driver in a partially updated state. Version
1436 * trauma will most likely occur if an client attempts to use any printer
1437 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1438 * done is appropriate... later JRR
1441 DEBUG(5,("Moving files now !\n"));
1443 if (driver->driverpath && strlen(driver->driverpath)) {
1444 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1445 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1446 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1448 status = rename_internals(conn, new_name, old_name, True);
1449 if (!NT_STATUS_IS_OK(status)) {
1450 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1451 new_name, old_name));
1452 *perr = ntstatus_to_werror(status);
1453 unlink_internals(conn, 0, new_name);
1458 unlink_internals(conn, 0, new_name);
1461 if (driver->datafile && strlen(driver->datafile)) {
1462 if (!strequal(driver->datafile, driver->driverpath)) {
1463 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1464 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1465 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1467 status = rename_internals(conn, new_name, old_name, True);
1468 if (!NT_STATUS_IS_OK(status)) {
1469 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1470 new_name, old_name));
1471 *perr = ntstatus_to_werror(status);
1472 unlink_internals(conn, 0, new_name);
1477 unlink_internals(conn, 0, new_name);
1481 if (driver->configfile && strlen(driver->configfile)) {
1482 if (!strequal(driver->configfile, driver->driverpath) &&
1483 !strequal(driver->configfile, driver->datafile)) {
1484 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1485 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1486 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1488 status = rename_internals(conn, new_name, old_name, True);
1489 if (!NT_STATUS_IS_OK(status)) {
1490 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1491 new_name, old_name));
1492 *perr = ntstatus_to_werror(status);
1493 unlink_internals(conn, 0, new_name);
1498 unlink_internals(conn, 0, new_name);
1502 if (driver->helpfile && strlen(driver->helpfile)) {
1503 if (!strequal(driver->helpfile, driver->driverpath) &&
1504 !strequal(driver->helpfile, driver->datafile) &&
1505 !strequal(driver->helpfile, driver->configfile)) {
1506 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1507 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1508 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1510 status = rename_internals(conn, new_name, old_name, True);
1511 if (!NT_STATUS_IS_OK(status)) {
1512 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1513 new_name, old_name));
1514 *perr = ntstatus_to_werror(status);
1515 unlink_internals(conn, 0, new_name);
1520 unlink_internals(conn, 0, new_name);
1524 if (driver->dependentfiles) {
1525 for (i=0; *driver->dependentfiles[i]; i++) {
1526 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1527 !strequal(driver->dependentfiles[i], driver->datafile) &&
1528 !strequal(driver->dependentfiles[i], driver->configfile) &&
1529 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1531 for (j=0; j < i; j++) {
1532 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1537 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1538 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1539 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1541 status = rename_internals(conn, new_name, old_name, True);
1542 if (!NT_STATUS_IS_OK(status)) {
1543 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1544 new_name, old_name));
1545 *perr = ntstatus_to_werror(status);
1546 unlink_internals(conn, 0, new_name);
1551 unlink_internals(conn, 0, new_name);
1557 close_cnum(conn, user->vuid);
1560 return ver == -1 ? False : True;
1563 /****************************************************************************
1564 ****************************************************************************/
1565 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1568 fstring architecture;
1574 TDB_DATA kbuf, dbuf;
1576 get_short_archi(architecture, driver->environment);
1578 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1579 * \\server is added in the rpc server layer.
1580 * It does make sense to NOT store the server's name in the printer TDB.
1583 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1585 /* .inf files do not always list a file for each of the four standard files.
1586 * Don't prepend a path to a null filename, or client claims:
1587 * "The server on which the printer resides does not have a suitable
1588 * <printer driver name> printer driver installed. Click OK if you
1589 * wish to install the driver on your local machine."
1591 if (strlen(driver->driverpath)) {
1592 fstrcpy(temp_name, driver->driverpath);
1593 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1596 if (strlen(driver->datafile)) {
1597 fstrcpy(temp_name, driver->datafile);
1598 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1601 if (strlen(driver->configfile)) {
1602 fstrcpy(temp_name, driver->configfile);
1603 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1606 if (strlen(driver->helpfile)) {
1607 fstrcpy(temp_name, driver->helpfile);
1608 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1611 if (driver->dependentfiles) {
1612 for (i=0; *driver->dependentfiles[i]; i++) {
1613 fstrcpy(temp_name, driver->dependentfiles[i]);
1614 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1618 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1620 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1627 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1630 driver->environment,
1635 driver->monitorname,
1636 driver->defaultdatatype);
1638 if (driver->dependentfiles) {
1639 for (i=0; *driver->dependentfiles[i]; i++) {
1640 len += tdb_pack(buf+len, buflen-len, "f",
1641 driver->dependentfiles[i]);
1645 if (len != buflen) {
1648 tb = (char *)Realloc(buf, len);
1650 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1661 kbuf.dsize = strlen(key)+1;
1665 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1669 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1675 /****************************************************************************
1676 ****************************************************************************/
1677 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1679 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1682 info3.cversion = driver->version;
1683 fstrcpy(info3.name,driver->name);
1684 fstrcpy(info3.environment,driver->environment);
1685 fstrcpy(info3.driverpath,driver->driverpath);
1686 fstrcpy(info3.datafile,driver->datafile);
1687 fstrcpy(info3.configfile,driver->configfile);
1688 fstrcpy(info3.helpfile,driver->helpfile);
1689 fstrcpy(info3.monitorname,driver->monitorname);
1690 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1691 info3.dependentfiles = driver->dependentfiles;
1693 return add_a_printer_driver_3(&info3);
1697 /****************************************************************************
1698 ****************************************************************************/
1699 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring driver, fstring arch)
1701 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1705 fstrcpy(info.name, driver);
1706 fstrcpy(info.defaultdatatype, "RAW");
1708 fstrcpy(info.driverpath, "");
1709 fstrcpy(info.datafile, "");
1710 fstrcpy(info.configfile, "");
1711 fstrcpy(info.helpfile, "");
1713 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1716 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1717 fstrcpy(info.dependentfiles[0], "");
1719 *info_ptr = memdup(&info, sizeof(info));
1724 /****************************************************************************
1725 ****************************************************************************/
1726 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, fstring arch, uint32 version)
1728 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1729 TDB_DATA kbuf, dbuf;
1730 fstring architecture;
1735 ZERO_STRUCT(driver);
1737 get_short_archi(architecture, arch);
1739 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1741 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1744 kbuf.dsize = strlen(key)+1;
1746 dbuf = tdb_fetch(tdb_drivers, kbuf);
1748 return WERR_ACCESS_DENIED;
1750 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1759 driver.defaultdatatype);
1762 while (len < dbuf.dsize)
1766 tddfs = (fstring *)Realloc(driver.dependentfiles,
1767 sizeof(fstring)*(i+2));
1768 if (tddfs == NULL) {
1769 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1772 else driver.dependentfiles = tddfs;
1774 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1775 &driver.dependentfiles[i]);
1779 if (driver.dependentfiles != NULL)
1780 fstrcpy(driver.dependentfiles[i], "");
1782 SAFE_FREE(dbuf.dptr);
1784 if (len != dbuf.dsize)
1786 SAFE_FREE(driver.dependentfiles);
1788 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1791 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1796 /****************************************************************************
1797 ****************************************************************************/
1798 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1800 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1806 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1807 DEBUG(10,("driver key: [%s]\n", key));
1810 kbuf.dsize = strlen(key)+1;
1811 if (!tdb_exists(tdb_drivers, kbuf))
1815 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1817 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1818 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1819 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1820 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1821 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1822 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1823 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1825 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1826 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1827 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1829 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1830 trim_string(info3->driverpath, "\\print$\\WIN40\\0\\", 0);
1831 pstrcat(line, info3->driverpath);
1833 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1834 pstrcat(line, info3->datafile);
1836 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1837 pstrcat(line, info3->helpfile);
1839 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1840 pstrcat(line, info3->monitorname);
1842 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1845 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1847 pstrcat(line, ","); /* don't end in a "," */
1848 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1849 pstrcat(line, info3->dependentfiles[i]);
1857 /****************************************************************************
1858 Debugging function, dump at level 6 the struct in the logs.
1859 ****************************************************************************/
1861 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1864 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1867 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1873 if (driver.info_3 == NULL)
1876 info3=driver.info_3;
1878 DEBUGADD(20,("version:[%d]\n", info3->cversion));
1879 DEBUGADD(20,("name:[%s]\n", info3->name));
1880 DEBUGADD(20,("environment:[%s]\n", info3->environment));
1881 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
1882 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
1883 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
1884 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
1885 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
1886 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1888 for (i=0; info3->dependentfiles &&
1889 *info3->dependentfiles[i]; i++) {
1890 DEBUGADD(20,("dependentfile:[%s]\n",
1891 info3->dependentfiles[i]));
1898 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1906 /****************************************************************************
1907 ****************************************************************************/
1908 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1912 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1914 if (!nt_devmode) return len;
1916 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1917 nt_devmode->devicename,
1918 nt_devmode->formname,
1920 nt_devmode->specversion,
1921 nt_devmode->driverversion,
1923 nt_devmode->driverextra,
1924 nt_devmode->orientation,
1925 nt_devmode->papersize,
1926 nt_devmode->paperlength,
1927 nt_devmode->paperwidth,
1930 nt_devmode->defaultsource,
1931 nt_devmode->printquality,
1934 nt_devmode->yresolution,
1935 nt_devmode->ttoption,
1936 nt_devmode->collate,
1937 nt_devmode->logpixels,
1940 nt_devmode->bitsperpel,
1941 nt_devmode->pelswidth,
1942 nt_devmode->pelsheight,
1943 nt_devmode->displayflags,
1944 nt_devmode->displayfrequency,
1945 nt_devmode->icmmethod,
1946 nt_devmode->icmintent,
1947 nt_devmode->mediatype,
1948 nt_devmode->dithertype,
1949 nt_devmode->reserved1,
1950 nt_devmode->reserved2,
1951 nt_devmode->panningwidth,
1952 nt_devmode->panningheight,
1953 nt_devmode->private);
1956 if (nt_devmode->private) {
1957 len += tdb_pack(buf+len, buflen-len, "B",
1958 nt_devmode->driverextra,
1959 nt_devmode->private);
1962 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1967 /****************************************************************************
1968 Pack all values in all printer keys
1969 ***************************************************************************/
1971 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
1975 REGISTRY_VALUE *val;
1976 REGVAL_CTR *val_ctr;
1983 /* loop over all keys */
1985 for ( i=0; i<data->num_keys; i++ )
1987 val_ctr = &data->keys[i].values;
1988 num_values = regval_ctr_numvals( val_ctr );
1990 /* loop over all values */
1992 for ( j=0; j<num_values; j++ )
1994 /* pathname should be stored as <key>\<value> */
1996 val = regval_ctr_specific_value( val_ctr, j );
1997 pstrcpy( path, data->keys[i].name );
1998 pstrcat( path, "\\" );
1999 pstrcat( path, regval_name(val) );
2001 len += tdb_pack(buf+len, buflen-len, "pPdB",
2006 regval_data_p(val) );
2013 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2019 /****************************************************************************
2020 Delete a printer - this just deletes the printer info file, any open
2021 handles are not affected.
2022 ****************************************************************************/
2024 uint32 del_a_printer(char *sharename)
2029 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2032 kbuf.dsize=strlen(key)+1;
2034 tdb_delete(tdb_printers, kbuf);
2038 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
2039 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
2040 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
2041 /****************************************************************************
2042 ****************************************************************************/
2043 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2049 TDB_DATA kbuf, dbuf;
2052 * in addprinter: no servername and the printer is the name
2053 * in setprinter: servername is \\server
2054 * and printer is \\server\\printer
2056 * Samba manages only local printers.
2057 * we currently don't support things like path=\\other_server\printer
2060 if (info->servername[0]!='\0') {
2061 trim_string(info->printername, info->servername, NULL);
2062 trim_string(info->printername, "\\", NULL);
2063 info->servername[0]='\0';
2067 * JFM: one day I'll forget.
2068 * below that's info->portname because that's the SAMBA sharename
2069 * and I made NT 'thinks' it's the portname
2070 * the info->sharename is the thing you can name when you add a printer
2071 * that's the short-name when you create shared printer for 95/98
2072 * So I've made a limitation in SAMBA: you can only have 1 printer model
2073 * behind a SAMBA share.
2081 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2084 info->default_priority,
2101 info->printprocessor,
2105 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2107 len += pack_values( &info->data, buf+len, buflen-len );
2109 if (buflen != len) {
2112 tb = (char *)Realloc(buf, len);
2114 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2124 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2127 kbuf.dsize = strlen(key)+1;
2131 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2134 if (!W_ERROR_IS_OK(ret))
2135 DEBUG(8, ("error updating printer to tdb on disk\n"));
2139 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2140 info->sharename, info->drivername, info->portname, len));
2146 /****************************************************************************
2147 Malloc and return an NT devicemode.
2148 ****************************************************************************/
2150 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2154 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2156 if (nt_devmode == NULL) {
2157 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2161 ZERO_STRUCTP(nt_devmode);
2163 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2164 fstrcpy(nt_devmode->devicename, adevice);
2166 fstrcpy(nt_devmode->formname, "Letter");
2168 nt_devmode->specversion = 0x0401;
2169 nt_devmode->driverversion = 0x0400;
2170 nt_devmode->size = 0x00DC;
2171 nt_devmode->driverextra = 0x0000;
2172 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2173 DEFAULTSOURCE | COPIES | SCALE |
2174 PAPERSIZE | ORIENTATION;
2175 nt_devmode->orientation = 1;
2176 nt_devmode->papersize = PAPER_LETTER;
2177 nt_devmode->paperlength = 0;
2178 nt_devmode->paperwidth = 0;
2179 nt_devmode->scale = 0x64;
2180 nt_devmode->copies = 1;
2181 nt_devmode->defaultsource = BIN_FORMSOURCE;
2182 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2183 nt_devmode->color = COLOR_MONOCHROME;
2184 nt_devmode->duplex = DUP_SIMPLEX;
2185 nt_devmode->yresolution = 0;
2186 nt_devmode->ttoption = TT_SUBDEV;
2187 nt_devmode->collate = COLLATE_FALSE;
2188 nt_devmode->icmmethod = 0;
2189 nt_devmode->icmintent = 0;
2190 nt_devmode->mediatype = 0;
2191 nt_devmode->dithertype = 0;
2193 /* non utilisés par un driver d'imprimante */
2194 nt_devmode->logpixels = 0;
2195 nt_devmode->bitsperpel = 0;
2196 nt_devmode->pelswidth = 0;
2197 nt_devmode->pelsheight = 0;
2198 nt_devmode->displayflags = 0;
2199 nt_devmode->displayfrequency = 0;
2200 nt_devmode->reserved1 = 0;
2201 nt_devmode->reserved2 = 0;
2202 nt_devmode->panningwidth = 0;
2203 nt_devmode->panningheight = 0;
2205 nt_devmode->private = NULL;
2209 /****************************************************************************
2210 Deepcopy an NT devicemode.
2211 ****************************************************************************/
2213 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2215 NT_DEVICEMODE *new_nt_devicemode = NULL;
2217 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2218 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2222 new_nt_devicemode->private = NULL;
2223 if (nt_devicemode->private != NULL) {
2224 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2225 SAFE_FREE(new_nt_devicemode);
2226 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2231 return new_nt_devicemode;
2234 /****************************************************************************
2235 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2236 ****************************************************************************/
2238 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2240 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2242 if(nt_devmode == NULL)
2245 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2247 SAFE_FREE(nt_devmode->private);
2248 SAFE_FREE(*devmode_ptr);
2251 /****************************************************************************
2252 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2253 ****************************************************************************/
2254 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2256 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2257 NT_PRINTER_DATA *data;
2263 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2265 free_nt_devicemode(&info->devmode);
2267 /* clean up all registry keys */
2270 for ( i=0; i<data->num_keys; i++ )
2272 SAFE_FREE( data->keys[i].name );
2273 regval_ctr_destroy( &data->keys[i].values );
2275 SAFE_FREE( data->keys );
2277 /* finally the top level structure */
2279 SAFE_FREE( *info_ptr );
2283 /****************************************************************************
2284 ****************************************************************************/
2285 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2289 NT_DEVICEMODE devmode;
2291 ZERO_STRUCT(devmode);
2293 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2295 if (!*nt_devmode) return len;
2297 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2301 &devmode.specversion,
2302 &devmode.driverversion,
2304 &devmode.driverextra,
2305 &devmode.orientation,
2307 &devmode.paperlength,
2308 &devmode.paperwidth,
2311 &devmode.defaultsource,
2312 &devmode.printquality,
2315 &devmode.yresolution,
2321 &devmode.bitsperpel,
2323 &devmode.pelsheight,
2324 &devmode.displayflags,
2325 &devmode.displayfrequency,
2329 &devmode.dithertype,
2332 &devmode.panningwidth,
2333 &devmode.panningheight,
2336 if (devmode.private) {
2337 /* the len in tdb_unpack is an int value and
2338 * devmode.driverextra is only a short
2340 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2341 devmode.driverextra=(uint16)extra_len;
2343 /* check to catch an invalid TDB entry so we don't segfault */
2344 if (devmode.driverextra == 0) {
2345 devmode.private = NULL;
2349 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2351 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2352 if (devmode.private)
2353 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2358 /****************************************************************************
2359 allocate and initialize a new slot in
2360 ***************************************************************************/
2362 static int add_new_printer_key( NT_PRINTER_DATA *data, char *name )
2367 if ( !data || !name )
2370 /* allocate another slot in the NT_PRINTER_KEY array */
2372 d = Realloc( data->keys, sizeof(NT_PRINTER_KEY)*(data->num_keys+1) );
2376 key_index = data->num_keys;
2378 /* initialze new key */
2381 data->keys[key_index].name = strdup( name );
2383 ZERO_STRUCTP( &data->keys[key_index].values );
2385 regval_ctr_init( &data->keys[key_index].values );
2387 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2392 /****************************************************************************
2393 search for a registry key name in the existing printer data
2394 ***************************************************************************/
2396 int lookup_printerkey( NT_PRINTER_DATA *data, char *name )
2401 if ( !data || !name )
2404 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2406 /* loop over all existing keys */
2408 for ( i=0; i<data->num_keys; i++ )
2410 if ( strequal(data->keys[i].name, name) ) {
2411 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2421 /****************************************************************************
2422 ***************************************************************************/
2424 uint32 get_printer_subkeys( NT_PRINTER_DATA *data, char* key, fstring **subkeys )
2428 int num_subkeys = 0;
2430 fstring *ptr, *subkeys_ptr = NULL;
2435 for ( i=0; i<data->num_keys; i++ )
2437 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 )
2439 /* match sure it is a subkey and not the key itself */
2441 key_len = strlen( key );
2442 if ( strlen(data->keys[i].name) == key_len )
2445 /* get subkey path */
2447 p = data->keys[i].name + key_len;
2449 /* found a match, so allocate space and copy the name */
2451 if ( !(ptr = Realloc( subkeys_ptr, (num_subkeys+2)*sizeof(fstring))) ) {
2452 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2454 SAFE_FREE( subkeys );
2460 /* copy the subkey name and trim off any trailing
2463 fstrcpy( subkeys_ptr[num_subkeys], p );
2464 p = strchr( subkeys_ptr[num_subkeys], '\\' );
2472 /* tag of the end */
2474 fstrcpy( subkeys_ptr[num_subkeys], "" );
2476 *subkeys = subkeys_ptr;
2481 /****************************************************************************
2482 ***************************************************************************/
2484 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2 )
2486 WERROR result = WERR_OK;
2487 NT_PRINTER_DATA *data;
2492 for ( i=0; i<data->num_keys; i++ )
2494 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2495 data->keys[i].name));
2497 SAFE_FREE( data->keys[i].name );
2498 regval_ctr_destroy( &data->keys[i].values );
2501 SAFE_FREE( data->keys );
2503 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2506 ZERO_STRUCTP( data );
2511 /****************************************************************************
2512 ***************************************************************************/
2514 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value )
2516 WERROR result = WERR_OK;
2519 /* we must have names on non-zero length */
2521 if ( !key || !*key|| !value || !*value )
2522 return WERR_INVALID_NAME;
2524 /* find the printer key first */
2526 key_index = lookup_printerkey( &p2->data, key );
2527 if ( key_index == -1 )
2530 regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
2532 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2538 /****************************************************************************
2539 ***************************************************************************/
2541 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value,
2542 uint32 type, uint8 *data, int real_len )
2544 WERROR result = WERR_OK;
2547 /* we must have names on non-zero length */
2549 if ( !key || !*key|| !value || !*value )
2550 return WERR_INVALID_NAME;
2552 /* find the printer key first */
2554 key_index = lookup_printerkey( &p2->data, key );
2555 if ( key_index == -1 )
2556 key_index = add_new_printer_key( &p2->data, key );
2558 if ( key_index == -1 )
2561 regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
2562 type, data, real_len );
2564 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], size => [%d]\n",
2565 key, value, real_len ));
2570 /****************************************************************************
2571 ***************************************************************************/
2573 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value )
2577 if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
2580 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
2583 return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
2586 /****************************************************************************
2587 Unpack a list of registry values frem the TDB
2588 ***************************************************************************/
2590 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
2594 pstring string, valuename, keyname;
2598 REGISTRY_VALUE *regval_p;
2601 /* add the "PrinterDriverData" key first for performance reasons */
2603 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
2605 /* loop and unpack the rest of the registry values */
2610 /* check to see if there are any more registry values */
2612 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
2616 /* unpack the next regval */
2618 len += tdb_unpack(buf+len, buflen-len, "fdB",
2625 * break of the keyname from the value name.
2626 * Should only be one '\' in the string returned.
2629 str = strrchr( string, '\\');
2631 /* Put in "PrinterDriverData" is no key specified */
2634 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
2635 pstrcpy( valuename, string );
2639 pstrcpy( keyname, string );
2640 pstrcpy( valuename, str+1 );
2643 /* see if we need a new key */
2645 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
2646 key_index = add_new_printer_key( printer_data, keyname );
2648 if ( key_index == -1 ) {
2649 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
2654 /* add the new value */
2656 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, data_p, size );
2658 DEBUG(8,("specific: [%s\\%s], len: %d\n", keyname, valuename, size));
2664 /****************************************************************************
2665 ***************************************************************************/
2667 static void map_to_os2_driver(fstring drivername)
2669 static BOOL initialised=False;
2670 static fstring last_from,last_to;
2671 char *mapfile = lp_os2_driver_map();
2672 char **lines = NULL;
2676 if (!strlen(drivername))
2683 *last_from = *last_to = 0;
2687 if (strequal(drivername,last_from)) {
2688 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2689 fstrcpy(drivername,last_to);
2693 lines = file_lines_load(mapfile, &numlines);
2694 if (numlines == 0) {
2695 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2699 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2701 for( i = 0; i < numlines; i++) {
2702 char *nt_name = lines[i];
2703 char *os2_name = strchr(nt_name,'=');
2710 while (isspace(*nt_name))
2713 if (!*nt_name || strchr("#;",*nt_name))
2717 int l = strlen(nt_name);
2718 while (l && isspace(nt_name[l-1])) {
2724 while (isspace(*os2_name))
2728 int l = strlen(os2_name);
2729 while (l && isspace(os2_name[l-1])) {
2735 if (strequal(nt_name,drivername)) {
2736 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2737 fstrcpy(last_from,drivername);
2738 fstrcpy(last_to,os2_name);
2739 fstrcpy(drivername,os2_name);
2740 file_lines_free(lines);
2745 file_lines_free(lines);
2748 /****************************************************************************
2749 get a default printer info 2 struct
2750 ****************************************************************************/
2751 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2754 NT_PRINTER_INFO_LEVEL_2 info;
2758 snum = lp_servicenumber(sharename);
2760 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2761 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2762 get_called_name(), sharename);
2763 fstrcpy(info.sharename, sharename);
2764 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2765 fstrcpy(info.drivername, lp_printerdriver(snum));
2767 /* by setting the driver name to an empty string, a local NT admin
2768 can now run the **local** APW to install a local printer driver
2769 for a Samba shared printer in 2.2. Without this, drivers **must** be
2770 installed on the Samba server for NT clients --jerry */
2771 #if 0 /* JERRY --do not uncomment-- */
2772 if (!*info.drivername)
2773 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2777 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2779 pstrcpy(info.comment, "");
2780 fstrcpy(info.printprocessor, "winprint");
2781 fstrcpy(info.datatype, "RAW");
2783 info.attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK; /* attributes */
2785 info.starttime = 0; /* Minutes since 12:00am GMT */
2786 info.untiltime = 0; /* Minutes since 12:00am GMT */
2788 info.default_priority = 1;
2789 info.setuptime = (uint32)time(NULL);
2792 * I changed this as I think it is better to have a generic
2793 * DEVMODE than to crash Win2k explorer.exe --jerry
2794 * See the HP Deskjet 990c Win2k drivers for an example.
2796 * However the default devmode appears to cause problems
2797 * with the HP CLJ 8500 PCL driver. Hence the addition of
2798 * the "default devmode" parameter --jerry 22/01/2002
2801 if (lp_default_devmode(snum)) {
2802 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2806 info.devmode = NULL;
2809 /* This will get the current RPC talloc context, but we should be
2810 passing this as a parameter... fixme... JRA ! */
2812 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2815 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2817 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2825 free_nt_devicemode(&info.devmode);
2826 return WERR_ACCESS_DENIED;
2829 /****************************************************************************
2830 ****************************************************************************/
2831 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2834 NT_PRINTER_INFO_LEVEL_2 info;
2836 TDB_DATA kbuf, dbuf;
2837 fstring printername;
2841 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2844 kbuf.dsize = strlen(key)+1;
2846 dbuf = tdb_fetch(tdb_printers, kbuf);
2848 return get_a_printer_2_default(info_ptr, sharename);
2850 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2853 &info.default_priority,
2870 info.printprocessor,
2874 /* Samba has to have shared raw drivers. */
2875 info.attributes |= (PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK);
2877 /* Restore the stripped strings. */
2878 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2879 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
2881 fstrcpy(info.printername, printername);
2883 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2886 * Some client drivers freak out if there is a NULL devmode
2887 * (probably the driver is not checking before accessing
2888 * the devmode pointer) --jerry
2890 * See comments in get_a_printer_2_default()
2893 if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode)
2895 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
2897 info.devmode = construct_nt_devicemode(printername);
2900 len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
2902 /* This will get the current RPC talloc context, but we should be
2903 passing this as a parameter... fixme... JRA ! */
2905 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2907 /* Fix for OS/2 drivers. */
2909 if (get_remote_arch() == RA_OS2)
2910 map_to_os2_driver(info.drivername);
2912 SAFE_FREE(dbuf.dptr);
2913 *info_ptr=memdup(&info, sizeof(info));
2915 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2916 sharename, info.printername, info.drivername));
2921 /****************************************************************************
2922 debugging function, dump at level 6 the struct in the logs
2923 ****************************************************************************/
2924 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2927 NT_PRINTER_INFO_LEVEL_2 *info2;
2929 DEBUG(106,("Dumping printer at level [%d]\n", level));
2935 if (printer.info_2 == NULL)
2939 info2=printer.info_2;
2941 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2942 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2943 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2944 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2945 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2946 DEBUGADD(106,("status:[%d]\n", info2->status));
2947 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2948 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2949 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2950 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2951 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2953 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2954 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2955 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2956 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2957 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2958 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2959 DEBUGADD(106,("location:[%s]\n", info2->location));
2960 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2961 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2962 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2963 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2969 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
2977 /****************************************************************************
2978 Get the parameters we can substitute in an NT print job.
2979 ****************************************************************************/
2981 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2983 NT_PRINTER_INFO_LEVEL *printer = NULL;
2985 **printername = **sharename = **portname = '\0';
2987 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2990 fstrcpy(*printername, printer->info_2->printername);
2991 fstrcpy(*sharename, printer->info_2->sharename);
2992 fstrcpy(*portname, printer->info_2->portname);
2994 free_a_printer(&printer, 2);
2997 /****************************************************************************
2998 Update the changeid time.
2999 This is SO NASTY as some drivers need this to change, others need it
3000 static. This value will change every second, and I must hope that this
3001 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3003 ****************************************************************************/
3005 static uint32 rev_changeid(void)
3009 get_process_uptime(&tv);
3012 /* Return changeid as msec since spooler restart */
3013 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3016 * This setting seems to work well but is too untested
3017 * to replace the above calculation. Left in for experiementation
3018 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3020 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3025 * The function below are the high level ones.
3026 * only those ones must be called from the spoolss code.
3030 /****************************************************************************
3031 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3032 ****************************************************************************/
3034 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3038 dump_a_printer(printer, level);
3045 * Update the changestamp. Emperical tests show that the
3046 * ChangeID is always updated,but c_setprinter is
3047 * global spooler variable (not per printer).
3050 /* ChangeID **must** be increasing over the lifetime
3051 of client's spoolss service in order for the
3052 client's cache to show updates */
3054 printer.info_2->changeid = rev_changeid();
3057 * Because one day someone will ask:
3058 * NT->NT An admin connection to a remote
3059 * printer show changes imeediately in
3060 * the properities dialog
3062 * A non-admin connection will only show the
3063 * changes after viewing the properites page
3064 * 2 times. Seems to be related to a
3065 * race condition in the client between the spooler
3066 * updating the local cache and the Explorer.exe GUI
3067 * actually displaying the properties.
3069 * This is fixed in Win2k. admin/non-admin
3070 * connections both display changes immediately.
3075 result=update_a_printer_2(printer.info_2);
3079 result=WERR_UNKNOWN_LEVEL;
3086 /****************************************************************************
3087 Initialize printer devmode & data with previously saved driver init values.
3088 ****************************************************************************/
3090 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3094 TDB_DATA kbuf, dbuf;
3095 NT_PRINTER_INFO_LEVEL_2 info;
3101 * Delete any printer data 'values' already set. When called for driver
3102 * replace, there will generally be some, but during an add printer, there
3103 * should not be any (if there are delete them).
3106 delete_all_printer_data( info_ptr );
3108 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3111 kbuf.dsize = strlen(key)+1;
3113 dbuf = tdb_fetch(tdb_drivers, kbuf);
3116 * When changing to a driver that has no init info in the tdb, remove
3117 * the previous drivers init info and leave the new on blank.
3119 free_nt_devicemode(&info_ptr->devmode);
3124 * Get the saved DEVMODE..
3127 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3130 * The saved DEVMODE contains the devicename from the printer used during
3131 * the initialization save. Change it to reflect the new printer.
3134 ZERO_STRUCT(info.devmode->devicename);
3135 fstrcpy(info.devmode->devicename, info_ptr->printername);
3139 * NT/2k does not change out the entire DeviceMode of a printer
3140 * when changing the driver. Only the driverextra, private, &
3141 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3143 * Later e4xamination revealed that Windows NT/2k does reset the
3144 * the printer's device mode, bit **only** when you change a
3145 * property of the device mode such as the page orientation.
3150 /* Bind the saved DEVMODE to the new the printer */
3152 free_nt_devicemode(&info_ptr->devmode);
3153 info_ptr->devmode = info.devmode;
3156 DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
3157 info_ptr->printername, info_ptr->drivername));
3159 /* Add the printer data 'values' to the new printer */
3161 len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3164 SAFE_FREE(dbuf.dptr);
3169 /****************************************************************************
3170 Initialize printer devmode & data with previously saved driver init values.
3171 When a printer is created using AddPrinter, the drivername bound to the
3172 printer is used to lookup previously saved driver initialization info, which
3173 is bound to the new printer.
3174 ****************************************************************************/
3176 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3178 BOOL result = False;
3183 result = set_driver_init_2(printer->info_2);
3187 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3195 /****************************************************************************
3196 Delete driver init data stored for a specified driver
3197 ****************************************************************************/
3199 BOOL del_driver_init(char *drivername)
3204 if (!drivername || !*drivername) {
3205 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3209 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3212 kbuf.dsize = strlen(key)+1;
3214 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3216 return (tdb_delete(tdb_drivers, kbuf) == 0);
3219 /****************************************************************************
3220 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3221 in the tdb. Note: this is different from the driver entry and the printer
3222 entry. There should be a single driver init entry for each driver regardless
3223 of whether it was installed from NT or 2K. Technically, they should be
3224 different, but they work out to the same struct.
3225 ****************************************************************************/
3227 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3231 int buflen, len, ret;
3232 TDB_DATA kbuf, dbuf;
3239 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3241 len += pack_values( &info->data, buf+len, buflen-len );
3243 if (buflen != len) {
3246 tb = (char *)Realloc(buf, len);
3248 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3257 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3260 kbuf.dsize = strlen(key)+1;
3264 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3268 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3272 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3273 info->sharename, info->drivername));
3278 /****************************************************************************
3279 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3280 ****************************************************************************/
3282 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3286 dump_a_printer(printer, level);
3292 result=update_driver_init_2(printer.info_2);
3303 /****************************************************************************
3304 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3305 ****************************************************************************/
3307 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
3310 NT_PRINTER_INFO_LEVEL *printer = NULL;
3314 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3320 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3321 DEBUG(0,("get_a_printer: malloc fail.\n"));
3324 ZERO_STRUCTP(printer);
3325 result=get_a_printer_2(&printer->info_2, sharename);
3326 if (W_ERROR_IS_OK(result)) {
3327 dump_a_printer(*printer, level);
3328 *pp_printer = printer;
3335 result=WERR_UNKNOWN_LEVEL;
3339 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
3344 /****************************************************************************
3345 Deletes a NT_PRINTER_INFO_LEVEL struct.
3346 ****************************************************************************/
3348 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3351 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3353 DEBUG(104,("freeing a printer at level [%d]\n", level));
3355 if (printer == NULL)
3362 if (printer->info_2 != NULL)
3364 free_nt_printer_info_level_2(&printer->info_2);
3378 SAFE_FREE(*pp_printer);
3382 /****************************************************************************
3383 ****************************************************************************/
3384 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3387 DEBUG(104,("adding a printer at level [%d]\n", level));
3388 dump_a_printer_driver(driver, level);
3394 result=add_a_printer_driver_3(driver.info_3);
3400 result=add_a_printer_driver_6(driver.info_6);
3410 /****************************************************************************
3411 ****************************************************************************/
3412 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3413 fstring drivername, fstring architecture, uint32 version)
3420 /* Sometime we just want any version of the driver */
3422 if ( version == DRIVER_ANY_VERSION ) {
3423 /* look for Win2k first and then for NT4 */
3424 result = get_a_printer_driver_3(&driver->info_3, drivername,
3427 if ( !W_ERROR_IS_OK(result) ) {
3428 result = get_a_printer_driver_3( &driver->info_3,
3429 drivername, architecture, 2 );
3433 result = get_a_printer_driver_3(&driver->info_3, drivername,
3434 architecture, version);
3443 if (W_ERROR_IS_OK(result))
3444 dump_a_printer_driver(*driver, level);
3449 /****************************************************************************
3450 ****************************************************************************/
3451 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3459 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3460 if (driver.info_3 != NULL)
3462 info3=driver.info_3;
3463 SAFE_FREE(info3->dependentfiles);
3464 ZERO_STRUCTP(info3);
3476 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3477 if (driver.info_6 != NULL)
3479 info6=driver.info_6;
3480 SAFE_FREE(info6->dependentfiles);
3481 SAFE_FREE(info6->previousnames);
3482 ZERO_STRUCTP(info6);
3500 /****************************************************************************
3501 Determine whether or not a particular driver is currently assigned
3503 ****************************************************************************/
3505 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i )
3508 int n_services = lp_numservices();
3509 NT_PRINTER_INFO_LEVEL *printer = NULL;
3514 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
3516 /* loop through the printers.tdb and check for the drivername */
3518 for (snum=0; snum<n_services; snum++)
3520 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
3523 if ( !W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) )
3526 if ( !StrCaseCmp(i->name, printer->info_2->drivername) ) {
3527 free_a_printer( &printer, 2 );
3531 free_a_printer( &printer, 2 );
3534 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
3536 /* report that the driver is not in use by default */
3542 /**********************************************************************
3543 Check to see if a ogiven file is in use by *info
3544 *********************************************************************/
3546 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
3553 if ( strequal(file, info->driverpath) )
3556 if ( strequal(file, info->datafile) )
3559 if ( strequal(file, info->configfile) )
3562 if ( strequal(file, info->helpfile) )
3565 s = (char*) info->dependentfiles;
3570 if ( strequal(file, s) )
3580 /**********************************************************************
3581 Utility function to remove the dependent file pointed to by the
3582 input parameter from the list
3583 *********************************************************************/
3585 static void trim_dependent_file( char* s )
3589 /* set p to the next character string in the list */
3591 p = s + strlen( s ) + 1;
3593 /* check to see that we have another string to copy back */
3597 /* loop over s copying characters from p to s */
3598 while ( *p!='\0' && *(p+1)!='\0' )
3602 /* add the two trailing NULL's */
3608 /**********************************************************************
3609 Check if any of the files used by src are also used by drv
3610 *********************************************************************/
3612 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
3613 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
3615 BOOL in_use = False;
3621 /* check each file. Remove it from the src structure if it overlaps */
3623 if ( drv_file_in_use(src->driverpath, drv) ) {
3625 fstrcpy( src->driverpath, "" );
3628 if ( drv_file_in_use(src->datafile, drv) ) {
3630 fstrcpy( src->datafile, "" );
3633 if ( drv_file_in_use(src->configfile, drv) ) {
3635 fstrcpy( src->configfile, "" );
3638 s = (char*)src->dependentfiles;
3643 if ( drv_file_in_use(s, drv) ) {
3645 trim_dependent_file( s );
3656 /****************************************************************************
3657 Determine whether or not a particular driver files are currently being
3658 used by any other driver.
3660 Return value is True if any files were in use by other drivers
3661 and False otherwise.
3663 Upon return, *info has been modified to only contain the driver files
3664 which are not in use
3665 ****************************************************************************/
3667 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
3672 fstring *list = NULL;
3673 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3675 /* loop over all driver versions */
3677 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
3679 for ( version=0; version<DRIVER_MAX_VERSION; version++ )
3681 /* get the list of drivers */
3684 ndrivers = get_ntdrivers(&list, info->environment, version);
3686 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
3687 ndrivers, info->environment, version));
3692 /* check each driver for overlap in files */
3694 for (i=0; i<ndrivers; i++)
3696 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
3698 ZERO_STRUCT(driver);
3700 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i],
3701 info->environment, version)) )
3707 /* check if d2 uses any files from d1 */
3708 /* only if this is a different driver than the one being deleted */
3710 if ( !strequal(info->name, driver.info_3->name)
3711 || (info->cversion != driver.info_3->cversion) )
3713 if ( trim_overlap_drv_files(info, driver.info_3) ) {
3714 free_a_printer_driver(driver, 3);
3720 free_a_printer_driver(driver, 3);
3726 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
3731 /****************************************************************************
3732 Actually delete the driver files. Make sure that
3733 printer_driver_files_in_use() return False before calling
3735 ****************************************************************************/
3737 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user )
3740 connection_struct *conn;
3747 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", i->name, i->cversion));
3750 * Connect to the print$ share under the same account as the
3751 * user connected to the rpc pipe. Note we must be root to
3756 null_pw = data_blob( NULL, 0 );
3757 conn = make_connection_with_chdir( "print$", null_pw, "A:", user->vuid, &nt_status );
3761 DEBUG(0,("delete_driver_files: Unable to connect\n"));
3765 /* Save who we are - we are temporarily becoming the connection user. */
3767 if ( !become_user(conn, conn->vuid) ) {
3768 DEBUG(0,("delete_driver_files: Can't become user!\n"));
3772 /* now delete the files; must strip the '\print$' string from
3775 if ( *i->driverpath ) {
3776 if ( (s = strchr( &i->driverpath[1], '\\' )) != NULL ) {
3777 DEBUG(10,("deleting driverfile [%s]\n", s));
3778 unlink_internals(conn, 0, s);
3782 if ( *i->configfile ) {
3783 if ( (s = strchr( &i->configfile[1], '\\' )) != NULL ) {
3784 DEBUG(10,("deleting configfile [%s]\n", s));
3785 unlink_internals(conn, 0, s);
3789 if ( *i->datafile ) {
3790 if ( (s = strchr( &i->datafile[1], '\\' )) != NULL ) {
3791 DEBUG(10,("deleting datafile [%s]\n", s));
3792 unlink_internals(conn, 0, s);
3796 if ( *i->helpfile ) {
3797 if ( (s = strchr( &i->helpfile[1], '\\' )) != NULL ) {
3798 DEBUG(10,("deleting helpfile [%s]\n", s));
3799 unlink_internals(conn, 0, s);
3803 s = (char*)i->dependentfiles;
3808 if ( (file = strchr( s+1, '\\' )) != NULL )
3810 DEBUG(10,("deleting dependent file [%s]\n", file));
3811 unlink_internals(conn, 0, file );
3812 file += strlen( file ) + 1;
3821 /****************************************************************************
3822 Remove a printer driver from the TDB. This assumes that the the driver was
3823 previously looked up.
3824 ***************************************************************************/
3826 static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user,
3827 uint32 version, BOOL delete_files )
3831 TDB_DATA kbuf, dbuf;
3832 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
3834 /* delete the tdb data first */
3836 get_short_archi(arch, i->environment);
3837 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
3838 arch, version, i->name);
3840 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
3841 key, delete_files ? "TRUE" : "FALSE" ));
3844 dump_a_printer_driver( ctr, 3 );
3847 kbuf.dsize=strlen(key)+1;
3849 /* check if the driver actually exists for this environment */
3851 dbuf = tdb_fetch( tdb_drivers, kbuf );
3853 DEBUG(8,("delete_printer_driver_internal: Driver unknown [%s]\n", key));
3854 return WERR_UNKNOWN_PRINTER_DRIVER;
3857 SAFE_FREE( dbuf.dptr );
3859 /* ok... the driver exists so the delete should return success */
3861 if (tdb_delete(tdb_drivers, kbuf) == -1) {
3862 DEBUG (0,("delete_printer_driver_internal: fail to delete %s!\n", key));
3863 return WERR_ACCESS_DENIED;
3867 * now delete any associated files if delete_files == True
3868 * even if this part failes, we return succes because the
3869 * driver doesn not exist any more
3873 delete_driver_files( i, user );
3876 DEBUG(5,("delete_printer_driver_internal: driver delete successful [%s]\n", key));
3881 /****************************************************************************
3882 Remove a printer driver from the TDB. This assumes that the the driver was
3883 previously looked up.
3884 ***************************************************************************/
3886 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user,
3887 uint32 version, BOOL delete_files )
3892 * see if we should delete all versions of this driver
3893 * (DRIVER_ANY_VERSION uis only set for "Windows NT x86")
3896 if ( version == DRIVER_ANY_VERSION )
3898 /* Windows NT 4.0 */
3900 err = delete_printer_driver_internal(i, user, 2, delete_files );
3901 if ( !W_ERROR_IS_OK(err) && (W_ERROR_V(err) != ERRunknownprinterdriver ) )
3904 /* Windows 2000/XP */
3906 err = delete_printer_driver_internal(i, user, 3, delete_files );
3907 if ( !W_ERROR_IS_OK(err) && (W_ERROR_V(err) != ERRunknownprinterdriver ) )
3913 /* just delete what they asked for */
3915 return delete_printer_driver_internal(i, user, version, delete_files );
3918 /****************************************************************************
3919 Store a security desc for a printer.
3920 ****************************************************************************/
3922 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
3924 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3925 SEC_DESC_BUF *old_secdesc_ctr = NULL;
3927 TALLOC_CTX *mem_ctx = NULL;
3931 mem_ctx = talloc_init();
3932 if (mem_ctx == NULL)
3935 /* The old owner and group sids of the security descriptor are not
3936 present when new ACEs are added or removed by changing printer
3937 permissions through NT. If they are NULL in the new security
3938 descriptor then copy them over from the old one. */
3940 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3941 DOM_SID *owner_sid, *group_sid;
3942 SEC_ACL *dacl, *sacl;
3943 SEC_DESC *psd = NULL;
3946 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3948 /* Pick out correct owner and group sids */
3950 owner_sid = secdesc_ctr->sec->owner_sid ?
3951 secdesc_ctr->sec->owner_sid :
3952 old_secdesc_ctr->sec->owner_sid;
3954 group_sid = secdesc_ctr->sec->grp_sid ?
3955 secdesc_ctr->sec->grp_sid :
3956 old_secdesc_ctr->sec->grp_sid;
3958 dacl = secdesc_ctr->sec->dacl ?
3959 secdesc_ctr->sec->dacl :
3960 old_secdesc_ctr->sec->dacl;
3962 sacl = secdesc_ctr->sec->sacl ?
3963 secdesc_ctr->sec->sacl :
3964 old_secdesc_ctr->sec->sacl;
3966 /* Make a deep copy of the security descriptor */
3968 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3969 owner_sid, group_sid,
3974 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3977 if (!new_secdesc_ctr) {
3978 new_secdesc_ctr = secdesc_ctr;
3981 /* Store the security descriptor in a tdb */
3983 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3984 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3986 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3988 status = WERR_BADFUNC;
3992 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3994 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
3997 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3998 status = WERR_BADFUNC;
4001 /* Free malloc'ed memory */
4007 talloc_destroy(mem_ctx);
4011 /****************************************************************************
4012 Construct a default security descriptor buffer for a printer.
4013 ****************************************************************************/
4015 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4019 SEC_ACL *psa = NULL;
4020 SEC_DESC_BUF *sdb = NULL;
4021 SEC_DESC *psd = NULL;
4025 /* Create an ACE where Everyone is allowed to print */
4027 init_sec_access(&sa, PRINTER_ACE_PRINT);
4028 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4029 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4031 /* Make the security descriptor owned by the Administrators group
4032 on the PDC of the domain. */
4034 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4035 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4038 /* Backup plan - make printer owned by admins.
4039 This should emulate a lanman printer as security
4040 settings can't be changed. */
4042 sid_copy(&owner_sid, get_global_sam_sid());
4043 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4046 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4047 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4048 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4049 SEC_ACE_FLAG_INHERIT_ONLY);
4051 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4052 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4053 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4055 /* The ACL revision number in rpc_secdesc.h differs from the one
4056 created by NT when setting ACE entries in printer
4057 descriptors. NT4 complains about the property being edited by a
4060 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4061 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
4063 NULL, psa, &sd_size);
4067 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4071 sdb = make_sec_desc_buf(ctx, sd_size, psd);
4073 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4074 (unsigned int)sd_size));
4079 /****************************************************************************
4080 Get a security desc for a printer.
4081 ****************************************************************************/
4083 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4089 if ((temp = strchr(printername + 2, '\\'))) {
4090 printername = temp + 1;
4093 /* Fetch security descriptor from tdb */
4095 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4097 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4098 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4100 DEBUG(4,("using default secdesc for %s\n", printername));
4102 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4106 /* Save default security descriptor for later */
4108 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4109 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4111 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4112 tdb_prs_store(tdb_printers, key, &ps);
4119 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4120 this security descriptor has been created when winbindd was
4121 down. Take ownership of security descriptor. */
4123 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4126 /* Change sd owner to workgroup administrator */
4128 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4129 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4130 SEC_DESC *psd = NULL;
4135 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4137 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
4139 (*secdesc_ctr)->sec->grp_sid,
4140 (*secdesc_ctr)->sec->sacl,
4141 (*secdesc_ctr)->sec->dacl,
4144 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4146 /* Swap with other one */
4148 *secdesc_ctr = new_secdesc_ctr;
4152 nt_printing_setsec(printername, *secdesc_ctr);
4156 if (DEBUGLEVEL >= 10) {
4157 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4160 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4161 printername, the_acl->num_aces));
4163 for (i = 0; i < the_acl->num_aces; i++) {
4166 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4168 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4169 the_acl->ace[i].type, the_acl->ace[i].flags,
4170 the_acl->ace[i].info.mask));
4180 1: level not implemented
4181 2: file doesn't exist
4182 3: can't allocate memory
4183 4: can't free memory
4184 5: non existant struct
4188 A printer and a printer driver are 2 different things.
4189 NT manages them separatelly, Samba does the same.
4190 Why ? Simply because it's easier and it makes sense !
4192 Now explanation: You have 3 printers behind your samba server,
4193 2 of them are the same make and model (laser A and B). But laser B
4194 has an 3000 sheet feeder and laser A doesn't such an option.
4195 Your third printer is an old dot-matrix model for the accounting :-).
4197 If the /usr/local/samba/lib directory (default dir), you will have
4198 5 files to describe all of this.
4200 3 files for the printers (1 by printer):
4203 NTprinter_accounting
4204 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4205 NTdriver_printer model X
4206 NTdriver_printer model Y
4208 jfm: I should use this comment for the text file to explain
4209 same thing for the forms BTW.
4210 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4214 /* Convert generic access rights to printer object specific access rights.
4215 It turns out that NT4 security descriptors use generic access rights and
4216 NT5 the object specific ones. */
4218 void map_printer_permissions(SEC_DESC *sd)
4222 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4223 se_map_generic(&sd->dacl->ace[i].info.mask,
4224 &printer_generic_mapping);
4228 /****************************************************************************
4229 Check a user has permissions to perform the given operation. We use the
4230 permission constants defined in include/rpc_spoolss.h to check the various
4231 actions we perform when checking printer access.
4233 PRINTER_ACCESS_ADMINISTER:
4234 print_queue_pause, print_queue_resume, update_printer_sec,
4235 update_printer, spoolss_addprinterex_level_2,
4236 _spoolss_setprinterdata
4241 JOB_ACCESS_ADMINISTER:
4242 print_job_delete, print_job_pause, print_job_resume,
4245 ****************************************************************************/
4246 BOOL print_access_check(struct current_user *user, int snum, int access_type)
4248 SEC_DESC_BUF *secdesc = NULL;
4249 uint32 access_granted;
4253 TALLOC_CTX *mem_ctx = NULL;
4254 extern struct current_user current_user;
4256 /* If user is NULL then use the current_user structure */
4259 user = ¤t_user;
4261 /* Always allow root or printer admins to do anything */
4263 if (user->uid == 0 ||
4264 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
4268 /* Get printer name */
4270 pname = PRINTERNAME(snum);
4272 if (!pname || !*pname) {
4277 /* Get printer security descriptor */
4279 if(!(mem_ctx = talloc_init())) {
4284 nt_printing_getsec(mem_ctx, pname, &secdesc);
4286 if (access_type == JOB_ACCESS_ADMINISTER) {
4287 SEC_DESC_BUF *parent_secdesc = secdesc;
4289 /* Create a child security descriptor to check permissions
4290 against. This is because print jobs are child objects
4291 objects of a printer. */
4293 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4295 /* Now this is the bit that really confuses me. The access
4296 type needs to be changed from JOB_ACCESS_ADMINISTER to
4297 PRINTER_ACCESS_ADMINISTER for this to work. Something
4298 to do with the child (job) object becoming like a
4301 access_type = PRINTER_ACCESS_ADMINISTER;
4306 map_printer_permissions(secdesc->sec);
4308 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4309 &access_granted, &status);
4311 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4313 talloc_destroy(mem_ctx);
4321 /****************************************************************************
4322 Check the time parameters allow a print operation.
4323 *****************************************************************************/
4325 BOOL print_time_access_check(int snum)
4327 NT_PRINTER_INFO_LEVEL *printer = NULL;
4329 time_t now = time(NULL);
4333 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4336 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
4340 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4342 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
4345 free_a_printer(&printer, 2);