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
322 message_register(MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer);
326 /*******************************************************************
327 tdb traversal function for counting printers.
328 ********************************************************************/
330 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
331 TDB_DATA data, void *context)
333 int *printer_count = (int*)context;
335 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
337 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
343 /*******************************************************************
344 Update the spooler global c_setprinter. This variable is initialized
345 when the parent smbd starts with the number of existing printers. It
346 is monotonically increased by the current number of printers *after*
347 each add or delete printer RPC. Only Microsoft knows why... JRR020119
348 ********************************************************************/
350 uint32 update_c_setprinter(BOOL initialize)
353 int32 printer_count = 0;
355 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
357 /* Traverse the tdb, counting the printers */
358 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
360 /* If initializing, set c_setprinter to current printers count
361 * otherwise, bump it by the current printer count
364 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
366 c_setprinter = printer_count;
368 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
369 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
371 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
373 return (uint32)c_setprinter;
376 /*******************************************************************
377 Get the spooler global c_setprinter, accounting for initialization.
378 ********************************************************************/
380 uint32 get_c_setprinter(void)
382 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
384 if (c_setprinter == (int32)-1)
385 c_setprinter = update_c_setprinter(True);
387 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
389 return (uint32)c_setprinter;
392 /****************************************************************************
393 Get builtin form struct list.
394 ****************************************************************************/
396 int get_builtin_ntforms(nt_forms_struct **list)
398 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
399 return sizeof(default_forms) / sizeof(default_forms[0]);
402 /****************************************************************************
403 get a builtin form struct
404 ****************************************************************************/
406 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
410 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
411 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
412 count = sizeof(default_forms) / sizeof(default_forms[0]);
413 for (i=0;i<count;i++) {
414 if (strequal(form_name,default_forms[i].name)) {
415 DEBUGADD(6,("Found builtin form %s \n", form_name));
416 memcpy(form,&default_forms[i],sizeof(*form));
424 /****************************************************************************
425 get a form struct list
426 ****************************************************************************/
427 int get_ntforms(nt_forms_struct **list)
429 TDB_DATA kbuf, newkey, dbuf;
431 nt_forms_struct form;
436 for (kbuf = tdb_firstkey(tdb_forms);
438 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
439 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
441 dbuf = tdb_fetch(tdb_forms, kbuf);
442 if (!dbuf.dptr) continue;
444 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
445 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
446 &i, &form.flag, &form.width, &form.length, &form.left,
447 &form.top, &form.right, &form.bottom);
448 SAFE_FREE(dbuf.dptr);
449 if (ret != dbuf.dsize) continue;
451 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
453 DEBUG(0,("get_ntforms: Realloc fail.\n"));
465 /****************************************************************************
466 write a form struct list
467 ****************************************************************************/
468 int write_ntforms(nt_forms_struct **list, int number)
475 for (i=0;i<number;i++) {
476 /* save index, so list is rebuilt in correct order */
477 len = tdb_pack(buf, sizeof(buf), "dddddddd",
478 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
479 (*list)[i].left, (*list)[i].top, (*list)[i].right,
481 if (len > sizeof(buf)) break;
482 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
483 kbuf.dsize = strlen(key)+1;
487 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
493 /****************************************************************************
494 add a form struct at the end of the list
495 ****************************************************************************/
496 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
504 * NT tries to add forms even when
505 * they are already in the base
506 * only update the values if already present
511 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
512 for (n=0; n<*count; n++) {
513 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
514 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
521 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
522 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
526 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
530 (*list)[n].flag=form->flags;
531 (*list)[n].width=form->size_x;
532 (*list)[n].length=form->size_y;
533 (*list)[n].left=form->left;
534 (*list)[n].top=form->top;
535 (*list)[n].right=form->right;
536 (*list)[n].bottom=form->bottom;
541 /****************************************************************************
542 delete a named form struct
543 ****************************************************************************/
544 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
553 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
555 for (n=0; n<*count; n++) {
556 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
557 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
563 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
564 *ret = WERR_INVALID_PARAM;
568 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
569 kbuf.dsize = strlen(key)+1;
571 if (tdb_delete(tdb_forms, kbuf) != 0) {
579 /****************************************************************************
581 ****************************************************************************/
582 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
586 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
588 DEBUG(106, ("[%s]\n", form_name));
589 for (n=0; n<count; n++)
591 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
592 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
596 if (n==count) return;
598 (*list)[n].flag=form->flags;
599 (*list)[n].width=form->size_x;
600 (*list)[n].length=form->size_y;
601 (*list)[n].left=form->left;
602 (*list)[n].top=form->top;
603 (*list)[n].right=form->right;
604 (*list)[n].bottom=form->bottom;
607 /****************************************************************************
608 get the nt drivers list
610 traverse the database and look-up the matching names
611 ****************************************************************************/
612 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
618 TDB_DATA kbuf, newkey;
620 get_short_archi(short_archi, architecture);
621 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
623 for (kbuf = tdb_firstkey(tdb_drivers);
625 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
626 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
628 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
629 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
634 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
641 /****************************************************************************
642 function to do the mapping between the long architecture name and
644 ****************************************************************************/
645 BOOL get_short_archi(char *short_archi, char *long_archi)
652 struct table archi_table[]=
654 {"Windows 4.0", "WIN40" },
655 {"Windows NT x86", "W32X86" },
656 {"Windows NT R4000", "W32MIPS" },
657 {"Windows NT Alpha_AXP", "W32ALPHA" },
658 {"Windows NT PowerPC", "W32PPC" },
664 DEBUG(107,("Getting architecture dependant directory\n"));
667 } while ( (archi_table[i].long_archi!=NULL ) &&
668 StrCaseCmp(long_archi, archi_table[i].long_archi) );
670 if (archi_table[i].long_archi==NULL) {
671 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
675 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
677 DEBUGADD(108,("index: [%d]\n", i));
678 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
679 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
684 /****************************************************************************
685 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
686 There are two case to be covered here: PE (Portable Executable) and NE (New
687 Executable) files. Both files support the same INFO structure, but PE files
688 store the signature in unicode, and NE files store it as !unicode.
689 returns -1 on error, 1 on version info found, and 0 on no version info found.
690 ****************************************************************************/
692 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
698 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
699 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
700 fname, PE_HEADER_SIZE));
704 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
705 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
706 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
708 goto no_version_info;
711 /* Is this really a DOS header? */
712 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
713 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
714 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
715 goto no_version_info;
718 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
719 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
720 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
722 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
723 goto no_version_info;
726 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
727 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
729 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
730 goto no_version_info;
733 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
734 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
736 int section_table_bytes;
738 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
739 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
740 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
741 /* At this point, we assume the file is in error. It still could be somthing
742 * else besides a PE file, but it unlikely at this point.
747 /* get the section table */
748 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
749 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
751 if ((buf=malloc(section_table_bytes)) == NULL) {
752 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
753 fname, section_table_bytes));
757 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
758 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
763 /* Iterate the section table looking for the resource section ".rsrc" */
764 for (i = 0; i < num_sections; i++) {
765 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
767 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
768 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
769 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
772 if ((buf=malloc(section_bytes)) == NULL) {
773 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
774 fname, section_bytes));
778 /* Seek to the start of the .rsrc section info */
779 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
780 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
785 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
786 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
791 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
792 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
793 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
794 /* Align to next long address */
795 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
797 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
798 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
799 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
801 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
802 fname, *major, *minor,
803 (*major>>16)&0xffff, *major&0xffff,
804 (*minor>>16)&0xffff, *minor&0xffff));
813 /* Version info not found, fall back to origin date/time */
814 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
818 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
819 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
820 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
821 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
822 /* At this point, we assume the file is in error. It still could be somthing
823 * else besides a NE file, but it unlikely at this point. */
827 /* Allocate a bit more space to speed up things */
829 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
830 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
831 fname, PE_HEADER_SIZE));
835 /* This is a HACK! I got tired of trying to sort through the messy
836 * 'NE' file format. If anyone wants to clean this up please have at
837 * it, but this works. 'NE' files will eventually fade away. JRR */
838 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
839 /* Cover case that should not occur in a well formed 'NE' .dll file */
840 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
842 for(i=0; i<byte_count; i++) {
843 /* Fast skip past data that can't possibly match */
844 if (buf[i] != 'V') continue;
846 /* Potential match data crosses buf boundry, move it to beginning
847 * of buf, and fill the buf with as much as it will hold. */
848 if (i>byte_count-VS_VERSION_INFO_SIZE) {
851 memcpy(buf, &buf[i], byte_count-i);
852 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
853 (byte_count-i))) < 0) {
855 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
860 byte_count = bc + (byte_count - i);
861 if (byte_count<VS_VERSION_INFO_SIZE) break;
866 /* Check that the full signature string and the magic number that
867 * follows exist (not a perfect solution, but the chances that this
868 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
869 * twice, as it is simpler to read the code. */
870 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
871 /* Compute skip alignment to next long address */
872 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
873 sizeof(VS_SIGNATURE)) & 3;
874 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
876 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
877 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
878 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
879 fname, *major, *minor,
880 (*major>>16)&0xffff, *major&0xffff,
881 (*minor>>16)&0xffff, *minor&0xffff));
888 /* Version info not found, fall back to origin date/time */
889 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
894 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
895 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
896 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
907 /****************************************************************************
908 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
909 share one or more files. During the MS installation process files are checked
910 to insure that only a newer version of a shared file is installed over an
911 older version. There are several possibilities for this comparison. If there
912 is no previous version, the new one is newer (obviously). If either file is
913 missing the version info structure, compare the creation date (on Unix use
914 the modification date). Otherwise chose the numerically larger version number.
915 ****************************************************************************/
916 static int file_version_is_newer(connection_struct *conn, fstring new_file,
919 BOOL use_version = True;
924 time_t new_create_time;
928 time_t old_create_time;
932 files_struct *fsp = NULL;
934 SMB_STRUCT_STAT stat_buf;
938 ZERO_STRUCT(stat_buf);
939 new_create_time = (time_t)0;
940 old_create_time = (time_t)0;
942 /* Get file version info (if available) for previous file (if it exists) */
943 pstrcpy(filepath, old_file);
945 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
947 fsp = open_file_shared(conn, filepath, &stat_buf,
948 SET_OPEN_MODE(DOS_OPEN_RDONLY),
949 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
950 0, 0, &access_mode, &action);
952 /* Old file not found, so by definition new file is in fact newer */
953 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
958 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
959 if (ret == -1) goto error_exit;
962 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
965 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
966 old_create_time = st.st_mtime;
967 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
970 close_file(fsp, True);
972 /* Get file version info (if available) for new file */
973 pstrcpy(filepath, new_file);
974 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
976 fsp = open_file_shared(conn, filepath, &stat_buf,
977 SET_OPEN_MODE(DOS_OPEN_RDONLY),
978 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
979 0, 0, &access_mode, &action);
981 /* New file not found, this shouldn't occur if the caller did its job */
982 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
987 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
988 if (ret == -1) goto error_exit;
991 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
994 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
995 new_create_time = st.st_mtime;
996 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
999 close_file(fsp, True);
1002 /* Compare versions and choose the larger version number */
1003 if (new_major > old_major ||
1004 (new_major == old_major && new_minor > old_minor)) {
1006 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1010 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1015 /* Compare modification time/dates and choose the newest time/date */
1016 if (new_create_time > old_create_time) {
1017 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1021 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1028 close_file(fsp, True);
1032 /****************************************************************************
1033 Determine the correct cVersion associated with an architecture and driver
1034 ****************************************************************************/
1035 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
1036 struct current_user *user, WERROR *perr)
1044 files_struct *fsp = NULL;
1047 connection_struct *conn;
1051 *perr = WERR_INVALID_PARAM;
1053 /* If architecture is Windows 95/98/ME, the version is always 0. */
1054 if (strcmp(architecture, "WIN40") == 0) {
1055 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1061 * Connect to the print$ share under the same account as the user connected
1062 * to the rpc pipe. Note we must still be root to do this.
1065 /* Null password is ok - we are already an authenticated user... */
1066 null_pw = data_blob(NULL, 0);
1068 conn = make_connection_with_chdir("print$", null_pw, "A:", user->vuid, &nt_status);
1072 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1073 *perr = ntstatus_to_werror(nt_status);
1077 /* We are temporarily becoming the connection user. */
1078 if (!become_user(conn, conn->vuid)) {
1079 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1080 *perr = WERR_ACCESS_DENIED;
1084 /* Open the driver file (Portable Executable format) and determine the
1085 * deriver the cversion. */
1086 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1088 unix_convert(driverpath,conn,NULL,&bad_path,&st);
1090 fsp = open_file_shared(conn, driverpath, &st,
1091 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1092 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1093 0, 0, &access_mode, &action);
1095 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1096 driverpath, errno));
1097 *perr = WERR_ACCESS_DENIED;
1103 int ret = get_file_version(fsp, driverpath, &major, &minor);
1104 if (ret == -1) goto error_exit;
1107 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1112 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1113 * for more details. Version in this case is not just the version of the
1114 * file, but the version in the sense of kernal mode (2) vs. user mode
1115 * (3) drivers. Other bits of the version fields are the version info.
1118 cversion = major & 0x0000ffff;
1120 case 2: /* WinNT drivers */
1121 case 3: /* Win2K drivers */
1125 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1126 driverpath, cversion));
1130 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1131 driverpath, major, minor));
1134 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1135 driverpath, cversion));
1137 close_file(fsp, True);
1138 close_cnum(conn, user->vuid);
1147 close_file(fsp, True);
1149 close_cnum(conn, user->vuid);
1154 /****************************************************************************
1155 ****************************************************************************/
1156 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1157 struct current_user *user)
1159 fstring architecture;
1165 /* clean up the driver name.
1166 * we can get .\driver.dll
1167 * or worse c:\windows\system\driver.dll !
1169 /* using an intermediate string to not have overlaping memcpy()'s */
1170 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1171 fstrcpy(new_name, p+1);
1172 fstrcpy(driver->driverpath, new_name);
1175 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1176 fstrcpy(new_name, p+1);
1177 fstrcpy(driver->datafile, new_name);
1180 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1181 fstrcpy(new_name, p+1);
1182 fstrcpy(driver->configfile, new_name);
1185 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1186 fstrcpy(new_name, p+1);
1187 fstrcpy(driver->helpfile, new_name);
1190 if (driver->dependentfiles) {
1191 for (i=0; *driver->dependentfiles[i]; i++) {
1192 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1193 fstrcpy(new_name, p+1);
1194 fstrcpy(driver->dependentfiles[i], new_name);
1199 get_short_archi(architecture, driver->environment);
1201 /* jfm:7/16/2000 the client always sends the cversion=0.
1202 * The server should check which version the driver is by reading
1203 * the PE header of driver->driverpath.
1205 * For Windows 95/98 the version is 0 (so the value sent is correct)
1206 * For Windows NT (the architecture doesn't matter)
1207 * NT 3.1: cversion=0
1208 * NT 3.5/3.51: cversion=1
1212 if ((driver->cversion = get_correct_cversion( architecture,
1213 driver->driverpath, user, &err)) == -1)
1219 /****************************************************************************
1220 ****************************************************************************/
1221 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
1222 struct current_user *user)
1224 fstring architecture;
1230 /* clean up the driver name.
1231 * we can get .\driver.dll
1232 * or worse c:\windows\system\driver.dll !
1234 /* using an intermediate string to not have overlaping memcpy()'s */
1235 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1236 fstrcpy(new_name, p+1);
1237 fstrcpy(driver->driverpath, new_name);
1240 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1241 fstrcpy(new_name, p+1);
1242 fstrcpy(driver->datafile, new_name);
1245 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1246 fstrcpy(new_name, p+1);
1247 fstrcpy(driver->configfile, new_name);
1250 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1251 fstrcpy(new_name, p+1);
1252 fstrcpy(driver->helpfile, new_name);
1255 if (driver->dependentfiles) {
1256 for (i=0; *driver->dependentfiles[i]; i++) {
1257 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1258 fstrcpy(new_name, p+1);
1259 fstrcpy(driver->dependentfiles[i], new_name);
1264 get_short_archi(architecture, driver->environment);
1266 /* jfm:7/16/2000 the client always sends the cversion=0.
1267 * The server should check which version the driver is by reading
1268 * the PE header of driver->driverpath.
1270 * For Windows 95/98 the version is 0 (so the value sent is correct)
1271 * For Windows NT (the architecture doesn't matter)
1272 * NT 3.1: cversion=0
1273 * NT 3.5/3.51: cversion=1
1277 if ((driver->version = get_correct_cversion(architecture,
1278 driver->driverpath, user, &err)) == -1)
1284 /****************************************************************************
1285 ****************************************************************************/
1286 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1287 uint32 level, struct current_user *user)
1292 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1293 driver=driver_abstract.info_3;
1294 return clean_up_driver_struct_level_3(driver, user);
1298 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1299 driver=driver_abstract.info_6;
1300 return clean_up_driver_struct_level_6(driver, user);
1303 return WERR_INVALID_PARAM;
1307 /****************************************************************************
1308 This function sucks and should be replaced. JRA.
1309 ****************************************************************************/
1311 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1313 dst->cversion = src->version;
1315 fstrcpy( dst->name, src->name);
1316 fstrcpy( dst->environment, src->environment);
1317 fstrcpy( dst->driverpath, src->driverpath);
1318 fstrcpy( dst->datafile, src->datafile);
1319 fstrcpy( dst->configfile, src->configfile);
1320 fstrcpy( dst->helpfile, src->helpfile);
1321 fstrcpy( dst->monitorname, src->monitorname);
1322 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1323 dst->dependentfiles = src->dependentfiles;
1326 #if 0 /* Debugging function */
1328 static char* ffmt(unsigned char *c){
1330 static char ffmt_str[17];
1332 for (i=0; i<16; i++) {
1333 if ((c[i] < ' ') || (c[i] > '~'))
1344 /****************************************************************************
1345 ****************************************************************************/
1346 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1347 struct current_user *user, WERROR *perr)
1349 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1350 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1351 fstring architecture;
1356 connection_struct *conn;
1363 memset(inbuf, '\0', sizeof(inbuf));
1364 memset(outbuf, '\0', sizeof(outbuf));
1368 driver=driver_abstract.info_3;
1369 else if (level==6) {
1370 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1371 driver = &converted_driver;
1373 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1377 get_short_archi(architecture, driver->environment);
1380 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1381 * Note we must be root to do this.
1385 null_pw = data_blob(NULL, 0);
1386 conn = make_connection_with_chdir("print$", null_pw, "A:", user->vuid, &nt_status);
1390 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1391 *perr = ntstatus_to_werror(nt_status);
1396 * Save who we are - we are temporarily becoming the connection user.
1399 if (!become_user(conn, conn->vuid)) {
1400 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1405 * make the directories version and version\driver_name
1406 * under the architecture directory.
1408 DEBUG(5,("Creating first directory\n"));
1409 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1410 mkdir_internal(conn, new_dir);
1412 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1413 * listed for this driver which has already been moved, skip it (note:
1414 * drivers may list the same file name several times. Then check if the
1415 * file already exists in archi\cversion\, if so, check that the version
1416 * info (or time stamps if version info is unavailable) is newer (or the
1417 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1418 * Otherwise, delete the file.
1420 * If a file is not moved to archi\cversion\ because of an error, all the
1421 * rest of the 'unmoved' driver files are removed from archi\. If one or
1422 * more of the driver's files was already moved to archi\cversion\, it
1423 * potentially leaves the driver in a partially updated state. Version
1424 * trauma will most likely occur if an client attempts to use any printer
1425 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1426 * done is appropriate... later JRR
1429 DEBUG(5,("Moving files now !\n"));
1431 if (driver->driverpath && strlen(driver->driverpath)) {
1432 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1433 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1434 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1436 status = rename_internals(conn, new_name, old_name, True);
1437 if (!NT_STATUS_IS_OK(status)) {
1438 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1439 new_name, old_name));
1440 *perr = ntstatus_to_werror(status);
1441 unlink_internals(conn, 0, new_name);
1446 unlink_internals(conn, 0, new_name);
1449 if (driver->datafile && strlen(driver->datafile)) {
1450 if (!strequal(driver->datafile, driver->driverpath)) {
1451 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1452 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1453 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1455 status = rename_internals(conn, new_name, old_name, True);
1456 if (!NT_STATUS_IS_OK(status)) {
1457 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1458 new_name, old_name));
1459 *perr = ntstatus_to_werror(status);
1460 unlink_internals(conn, 0, new_name);
1465 unlink_internals(conn, 0, new_name);
1469 if (driver->configfile && strlen(driver->configfile)) {
1470 if (!strequal(driver->configfile, driver->driverpath) &&
1471 !strequal(driver->configfile, driver->datafile)) {
1472 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1473 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1474 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1476 status = rename_internals(conn, new_name, old_name, True);
1477 if (!NT_STATUS_IS_OK(status)) {
1478 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1479 new_name, old_name));
1480 *perr = ntstatus_to_werror(status);
1481 unlink_internals(conn, 0, new_name);
1486 unlink_internals(conn, 0, new_name);
1490 if (driver->helpfile && strlen(driver->helpfile)) {
1491 if (!strequal(driver->helpfile, driver->driverpath) &&
1492 !strequal(driver->helpfile, driver->datafile) &&
1493 !strequal(driver->helpfile, driver->configfile)) {
1494 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1495 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1496 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1498 status = rename_internals(conn, new_name, old_name, True);
1499 if (!NT_STATUS_IS_OK(status)) {
1500 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1501 new_name, old_name));
1502 *perr = ntstatus_to_werror(status);
1503 unlink_internals(conn, 0, new_name);
1508 unlink_internals(conn, 0, new_name);
1512 if (driver->dependentfiles) {
1513 for (i=0; *driver->dependentfiles[i]; i++) {
1514 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1515 !strequal(driver->dependentfiles[i], driver->datafile) &&
1516 !strequal(driver->dependentfiles[i], driver->configfile) &&
1517 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1519 for (j=0; j < i; j++) {
1520 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1525 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1526 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1527 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1529 status = rename_internals(conn, new_name, old_name, True);
1530 if (!NT_STATUS_IS_OK(status)) {
1531 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1532 new_name, old_name));
1533 *perr = ntstatus_to_werror(status);
1534 unlink_internals(conn, 0, new_name);
1539 unlink_internals(conn, 0, new_name);
1545 close_cnum(conn, user->vuid);
1548 return ver == -1 ? False : True;
1551 /****************************************************************************
1552 ****************************************************************************/
1553 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1556 fstring architecture;
1562 TDB_DATA kbuf, dbuf;
1564 get_short_archi(architecture, driver->environment);
1566 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1567 * \\server is added in the rpc server layer.
1568 * It does make sense to NOT store the server's name in the printer TDB.
1571 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1573 /* .inf files do not always list a file for each of the four standard files.
1574 * Don't prepend a path to a null filename, or client claims:
1575 * "The server on which the printer resides does not have a suitable
1576 * <printer driver name> printer driver installed. Click OK if you
1577 * wish to install the driver on your local machine."
1579 if (strlen(driver->driverpath)) {
1580 fstrcpy(temp_name, driver->driverpath);
1581 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1584 if (strlen(driver->datafile)) {
1585 fstrcpy(temp_name, driver->datafile);
1586 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1589 if (strlen(driver->configfile)) {
1590 fstrcpy(temp_name, driver->configfile);
1591 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1594 if (strlen(driver->helpfile)) {
1595 fstrcpy(temp_name, driver->helpfile);
1596 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1599 if (driver->dependentfiles) {
1600 for (i=0; *driver->dependentfiles[i]; i++) {
1601 fstrcpy(temp_name, driver->dependentfiles[i]);
1602 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1606 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1608 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1615 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1618 driver->environment,
1623 driver->monitorname,
1624 driver->defaultdatatype);
1626 if (driver->dependentfiles) {
1627 for (i=0; *driver->dependentfiles[i]; i++) {
1628 len += tdb_pack(buf+len, buflen-len, "f",
1629 driver->dependentfiles[i]);
1633 if (len != buflen) {
1636 tb = (char *)Realloc(buf, len);
1638 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1649 kbuf.dsize = strlen(key)+1;
1653 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1657 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1663 /****************************************************************************
1664 ****************************************************************************/
1665 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1667 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1670 info3.cversion = driver->version;
1671 fstrcpy(info3.name,driver->name);
1672 fstrcpy(info3.environment,driver->environment);
1673 fstrcpy(info3.driverpath,driver->driverpath);
1674 fstrcpy(info3.datafile,driver->datafile);
1675 fstrcpy(info3.configfile,driver->configfile);
1676 fstrcpy(info3.helpfile,driver->helpfile);
1677 fstrcpy(info3.monitorname,driver->monitorname);
1678 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1679 info3.dependentfiles = driver->dependentfiles;
1681 return add_a_printer_driver_3(&info3);
1685 /****************************************************************************
1686 ****************************************************************************/
1687 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring driver, fstring arch)
1689 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1693 fstrcpy(info.name, driver);
1694 fstrcpy(info.defaultdatatype, "RAW");
1696 fstrcpy(info.driverpath, "");
1697 fstrcpy(info.datafile, "");
1698 fstrcpy(info.configfile, "");
1699 fstrcpy(info.helpfile, "");
1701 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1704 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1705 fstrcpy(info.dependentfiles[0], "");
1707 *info_ptr = memdup(&info, sizeof(info));
1712 /****************************************************************************
1713 ****************************************************************************/
1714 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, fstring arch, uint32 version)
1716 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1717 TDB_DATA kbuf, dbuf;
1718 fstring architecture;
1723 ZERO_STRUCT(driver);
1725 get_short_archi(architecture, arch);
1727 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1729 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1732 kbuf.dsize = strlen(key)+1;
1734 dbuf = tdb_fetch(tdb_drivers, kbuf);
1736 return WERR_ACCESS_DENIED;
1738 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1747 driver.defaultdatatype);
1750 while (len < dbuf.dsize) {
1753 tddfs = (fstring *)Realloc(driver.dependentfiles,
1754 sizeof(fstring)*(i+2));
1755 if (tddfs == NULL) {
1756 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1759 else driver.dependentfiles = tddfs;
1761 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1762 &driver.dependentfiles[i]);
1765 if (driver.dependentfiles != NULL)
1766 fstrcpy(driver.dependentfiles[i], "");
1768 SAFE_FREE(dbuf.dptr);
1770 if (len != dbuf.dsize) {
1771 SAFE_FREE(driver.dependentfiles);
1773 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1776 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1781 /****************************************************************************
1782 ****************************************************************************/
1783 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1785 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1791 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1792 DEBUG(10,("driver key: [%s]\n", key));
1795 kbuf.dsize = strlen(key)+1;
1796 if (!tdb_exists(tdb_drivers, kbuf))
1800 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1802 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1803 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1804 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1805 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1806 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1807 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1808 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1810 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1811 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1812 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1814 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1815 trim_string(info3->driverpath, "\\print$\\WIN40\\0\\", 0);
1816 pstrcat(line, info3->driverpath);
1818 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1819 pstrcat(line, info3->datafile);
1821 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1822 pstrcat(line, info3->helpfile);
1824 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1825 pstrcat(line, info3->monitorname);
1827 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1830 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1832 pstrcat(line, ","); /* don't end in a "," */
1833 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1834 pstrcat(line, info3->dependentfiles[i]);
1842 /****************************************************************************
1843 Debugging function, dump at level 6 the struct in the logs.
1844 ****************************************************************************/
1846 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1849 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1852 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1858 if (driver.info_3 == NULL)
1861 info3=driver.info_3;
1863 DEBUGADD(20,("version:[%d]\n", info3->cversion));
1864 DEBUGADD(20,("name:[%s]\n", info3->name));
1865 DEBUGADD(20,("environment:[%s]\n", info3->environment));
1866 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
1867 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
1868 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
1869 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
1870 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
1871 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1873 for (i=0; info3->dependentfiles &&
1874 *info3->dependentfiles[i]; i++) {
1875 DEBUGADD(20,("dependentfile:[%s]\n",
1876 info3->dependentfiles[i]));
1883 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1891 /****************************************************************************
1892 ****************************************************************************/
1893 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1897 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1899 if (!nt_devmode) return len;
1901 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1902 nt_devmode->devicename,
1903 nt_devmode->formname,
1905 nt_devmode->specversion,
1906 nt_devmode->driverversion,
1908 nt_devmode->driverextra,
1909 nt_devmode->orientation,
1910 nt_devmode->papersize,
1911 nt_devmode->paperlength,
1912 nt_devmode->paperwidth,
1915 nt_devmode->defaultsource,
1916 nt_devmode->printquality,
1919 nt_devmode->yresolution,
1920 nt_devmode->ttoption,
1921 nt_devmode->collate,
1922 nt_devmode->logpixels,
1925 nt_devmode->bitsperpel,
1926 nt_devmode->pelswidth,
1927 nt_devmode->pelsheight,
1928 nt_devmode->displayflags,
1929 nt_devmode->displayfrequency,
1930 nt_devmode->icmmethod,
1931 nt_devmode->icmintent,
1932 nt_devmode->mediatype,
1933 nt_devmode->dithertype,
1934 nt_devmode->reserved1,
1935 nt_devmode->reserved2,
1936 nt_devmode->panningwidth,
1937 nt_devmode->panningheight,
1938 nt_devmode->private);
1941 if (nt_devmode->private) {
1942 len += tdb_pack(buf+len, buflen-len, "B",
1943 nt_devmode->driverextra,
1944 nt_devmode->private);
1947 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1952 /****************************************************************************
1953 ****************************************************************************/
1954 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1958 while (param != NULL) {
1959 len += tdb_pack(buf+len, buflen-len, "pfdB",
1968 len += tdb_pack(buf+len, buflen-len, "p", param);
1974 /****************************************************************************
1975 Delete a printer - this just deletes the printer info file, any open
1976 handles are not affected.
1977 ****************************************************************************/
1979 uint32 del_a_printer(char *sharename)
1984 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1987 kbuf.dsize=strlen(key)+1;
1989 tdb_delete(tdb_printers, kbuf);
1993 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
1994 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1995 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1996 /****************************************************************************
1997 ****************************************************************************/
1998 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2004 TDB_DATA kbuf, dbuf;
2007 * in addprinter: no servername and the printer is the name
2008 * in setprinter: servername is \\server
2009 * and printer is \\server\\printer
2011 * Samba manages only local printers.
2012 * we currently don't support things like path=\\other_server\printer
2015 if (info->servername[0]!='\0') {
2016 trim_string(info->printername, info->servername, NULL);
2017 trim_string(info->printername, "\\", NULL);
2018 info->servername[0]='\0';
2022 * JFM: one day I'll forget.
2023 * below that's info->portname because that's the SAMBA sharename
2024 * and I made NT 'thinks' it's the portname
2025 * the info->sharename is the thing you can name when you add a printer
2026 * that's the short-name when you create shared printer for 95/98
2027 * So I've made a limitation in SAMBA: you can only have 1 printer model
2028 * behind a SAMBA share.
2036 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2039 info->default_priority,
2056 info->printprocessor,
2060 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2062 len += pack_specifics(info->specific, buf+len, buflen-len);
2064 if (buflen != len) {
2067 tb = (char *)Realloc(buf, len);
2069 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2079 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2082 kbuf.dsize = strlen(key)+1;
2086 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2089 if (!W_ERROR_IS_OK(ret))
2090 DEBUG(8, ("error updating printer to tdb on disk\n"));
2094 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2095 info->sharename, info->drivername, info->portname, len));
2101 /****************************************************************************
2102 ****************************************************************************/
2103 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
2105 NT_PRINTER_PARAM *current;
2107 DEBUG(108,("add_a_specific_param\n"));
2109 (*param)->next=NULL;
2111 if (info_2->specific == NULL)
2113 info_2->specific=*param;
2117 current=info_2->specific;
2118 while (current->next != NULL) {
2119 current=current->next;
2121 current->next=*param;
2127 /****************************************************************************
2128 ****************************************************************************/
2129 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
2131 NT_PRINTER_PARAM *current;
2132 NT_PRINTER_PARAM *previous;
2134 current=info_2->specific;
2137 if (current==NULL) return (False);
2139 if ( !strcmp(current->value, param->value) &&
2140 (strlen(current->value)==strlen(param->value)) ) {
2141 DEBUG(109,("deleting first value\n"));
2142 info_2->specific=current->next;
2143 SAFE_FREE(current->data);
2145 DEBUG(109,("deleted first value\n"));
2149 current=previous->next;
2151 while ( current!=NULL ) {
2152 if (!strcmp(current->value, param->value) &&
2153 strlen(current->value)==strlen(param->value) ) {
2154 DEBUG(109,("deleting current value\n"));
2155 previous->next=current->next;
2156 SAFE_FREE(current->data);
2158 DEBUG(109,("deleted current value\n"));
2162 previous=previous->next;
2163 current=current->next;
2168 /****************************************************************************
2169 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2170 ****************************************************************************/
2171 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2173 NT_PRINTER_PARAM *param = *param_ptr;
2178 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2180 SAFE_FREE(param->data);
2181 SAFE_FREE(*param_ptr);
2184 /****************************************************************************
2185 Malloc and return an NT devicemode.
2186 ****************************************************************************/
2188 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2192 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2194 if (nt_devmode == NULL) {
2195 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2199 ZERO_STRUCTP(nt_devmode);
2201 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2202 fstrcpy(nt_devmode->devicename, adevice);
2204 fstrcpy(nt_devmode->formname, "Letter");
2206 nt_devmode->specversion = 0x0401;
2207 nt_devmode->driverversion = 0x0400;
2208 nt_devmode->size = 0x00DC;
2209 nt_devmode->driverextra = 0x0000;
2210 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2211 DEFAULTSOURCE | COPIES | SCALE |
2212 PAPERSIZE | ORIENTATION;
2213 nt_devmode->orientation = 1;
2214 nt_devmode->papersize = PAPER_LETTER;
2215 nt_devmode->paperlength = 0;
2216 nt_devmode->paperwidth = 0;
2217 nt_devmode->scale = 0x64;
2218 nt_devmode->copies = 1;
2219 nt_devmode->defaultsource = BIN_FORMSOURCE;
2220 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2221 nt_devmode->color = COLOR_MONOCHROME;
2222 nt_devmode->duplex = DUP_SIMPLEX;
2223 nt_devmode->yresolution = 0;
2224 nt_devmode->ttoption = TT_SUBDEV;
2225 nt_devmode->collate = COLLATE_FALSE;
2226 nt_devmode->icmmethod = 0;
2227 nt_devmode->icmintent = 0;
2228 nt_devmode->mediatype = 0;
2229 nt_devmode->dithertype = 0;
2231 /* non utilisés par un driver d'imprimante */
2232 nt_devmode->logpixels = 0;
2233 nt_devmode->bitsperpel = 0;
2234 nt_devmode->pelswidth = 0;
2235 nt_devmode->pelsheight = 0;
2236 nt_devmode->displayflags = 0;
2237 nt_devmode->displayfrequency = 0;
2238 nt_devmode->reserved1 = 0;
2239 nt_devmode->reserved2 = 0;
2240 nt_devmode->panningwidth = 0;
2241 nt_devmode->panningheight = 0;
2243 nt_devmode->private = NULL;
2247 /****************************************************************************
2248 Deepcopy an NT devicemode.
2249 ****************************************************************************/
2251 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2253 NT_DEVICEMODE *new_nt_devicemode = NULL;
2255 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2256 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2260 new_nt_devicemode->private = NULL;
2261 if (nt_devicemode->private != NULL) {
2262 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2263 SAFE_FREE(new_nt_devicemode);
2264 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2269 return new_nt_devicemode;
2272 /****************************************************************************
2273 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2274 ****************************************************************************/
2276 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2278 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2280 if(nt_devmode == NULL)
2283 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2285 SAFE_FREE(nt_devmode->private);
2286 SAFE_FREE(*devmode_ptr);
2289 /****************************************************************************
2290 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2291 ****************************************************************************/
2292 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2294 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2295 NT_PRINTER_PARAM *param_ptr;
2300 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2302 free_nt_devicemode(&info->devmode);
2304 for(param_ptr = info->specific; param_ptr; ) {
2305 NT_PRINTER_PARAM *tofree = param_ptr;
2307 param_ptr = param_ptr->next;
2308 free_nt_printer_param(&tofree);
2311 SAFE_FREE(*info_ptr);
2315 /****************************************************************************
2316 ****************************************************************************/
2317 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2321 NT_DEVICEMODE devmode;
2323 ZERO_STRUCT(devmode);
2325 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2327 if (!*nt_devmode) return len;
2329 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2333 &devmode.specversion,
2334 &devmode.driverversion,
2336 &devmode.driverextra,
2337 &devmode.orientation,
2339 &devmode.paperlength,
2340 &devmode.paperwidth,
2343 &devmode.defaultsource,
2344 &devmode.printquality,
2347 &devmode.yresolution,
2353 &devmode.bitsperpel,
2355 &devmode.pelsheight,
2356 &devmode.displayflags,
2357 &devmode.displayfrequency,
2361 &devmode.dithertype,
2364 &devmode.panningwidth,
2365 &devmode.panningheight,
2368 if (devmode.private) {
2369 /* the len in tdb_unpack is an int value and
2370 * devmode.driverextra is only a short
2372 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2373 devmode.driverextra=(uint16)extra_len;
2375 /* check to catch an invalid TDB entry so we don't segfault */
2376 if (devmode.driverextra == 0) {
2377 devmode.private = NULL;
2381 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2383 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2384 if (devmode.private)
2385 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2390 /****************************************************************************
2391 ****************************************************************************/
2392 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2395 NT_PRINTER_PARAM param, *p;
2400 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2403 len += tdb_unpack(buf+len, buflen-len, "fdB",
2409 *list = memdup(¶m, sizeof(param));
2411 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2417 static void map_to_os2_driver(fstring drivername)
2419 static BOOL initialised=False;
2420 static fstring last_from,last_to;
2421 char *mapfile = lp_os2_driver_map();
2422 char **lines = NULL;
2426 if (!strlen(drivername))
2433 *last_from = *last_to = 0;
2437 if (strequal(drivername,last_from)) {
2438 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2439 fstrcpy(drivername,last_to);
2443 lines = file_lines_load(mapfile, &numlines);
2444 if (numlines == 0) {
2445 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2449 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2451 for( i = 0; i < numlines; i++) {
2452 char *nt_name = lines[i];
2453 char *os2_name = strchr(nt_name,'=');
2460 while (isspace(*nt_name))
2463 if (!*nt_name || strchr("#;",*nt_name))
2467 int l = strlen(nt_name);
2468 while (l && isspace(nt_name[l-1])) {
2474 while (isspace(*os2_name))
2478 int l = strlen(os2_name);
2479 while (l && isspace(os2_name[l-1])) {
2485 if (strequal(nt_name,drivername)) {
2486 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2487 fstrcpy(last_from,drivername);
2488 fstrcpy(last_to,os2_name);
2489 fstrcpy(drivername,os2_name);
2490 file_lines_free(lines);
2495 file_lines_free(lines);
2498 /****************************************************************************
2499 get a default printer info 2 struct
2500 ****************************************************************************/
2501 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2504 NT_PRINTER_INFO_LEVEL_2 info;
2508 snum = lp_servicenumber(sharename);
2510 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2511 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2512 get_called_name(), sharename);
2513 fstrcpy(info.sharename, sharename);
2514 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2515 fstrcpy(info.drivername, lp_printerdriver(snum));
2517 /* by setting the driver name to an empty string, a local NT admin
2518 can now run the **local** APW to install a local printer driver
2519 for a Samba shared printer in 2.2. Without this, drivers **must** be
2520 installed on the Samba server for NT clients --jerry */
2521 #if 0 /* JERRY --do not uncomment-- */
2522 if (!*info.drivername)
2523 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2527 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2529 pstrcpy(info.comment, "");
2530 fstrcpy(info.printprocessor, "winprint");
2531 fstrcpy(info.datatype, "RAW");
2533 info.attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK; /* attributes */
2535 info.starttime = 0; /* Minutes since 12:00am GMT */
2536 info.untiltime = 0; /* Minutes since 12:00am GMT */
2538 info.default_priority = 1;
2539 info.setuptime = (uint32)time(NULL);
2542 * I changed this as I think it is better to have a generic
2543 * DEVMODE than to crash Win2k explorer.exe --jerry
2544 * See the HP Deskjet 990c Win2k drivers for an example.
2546 * However the default devmode appears to cause problems
2547 * with the HP CLJ 8500 PCL driver. Hence the addition of
2548 * the "default devmode" parameter --jerry 22/01/2002
2551 if (lp_default_devmode(snum)) {
2552 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2556 info.devmode = NULL;
2559 /* This will get the current RPC talloc context, but we should be
2560 passing this as a parameter... fixme... JRA ! */
2562 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2565 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2567 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2575 free_nt_devicemode(&info.devmode);
2576 return WERR_ACCESS_DENIED;
2579 /****************************************************************************
2580 ****************************************************************************/
2581 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2584 NT_PRINTER_INFO_LEVEL_2 info;
2586 TDB_DATA kbuf, dbuf;
2587 fstring printername;
2591 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2594 kbuf.dsize = strlen(key)+1;
2596 dbuf = tdb_fetch(tdb_printers, kbuf);
2598 return get_a_printer_2_default(info_ptr, sharename);
2600 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2603 &info.default_priority,
2620 info.printprocessor,
2624 /* Samba has to have shared raw drivers. */
2625 info.attributes |= (PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK);
2627 /* Restore the stripped strings. */
2628 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2629 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
2631 fstrcpy(info.printername, printername);
2633 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2636 * Some client drivers freak out if there is a NULL devmode
2637 * (probably the driver is not checking before accessing
2638 * the devmode pointer) --jerry
2640 * See comments in get_a_printer_2_default()
2643 if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode)
2645 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
2647 info.devmode = construct_nt_devicemode(printername);
2650 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2652 /* This will get the current RPC talloc context, but we should be
2653 passing this as a parameter... fixme... JRA ! */
2655 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2657 /* Fix for OS/2 drivers. */
2659 if (get_remote_arch() == RA_OS2)
2660 map_to_os2_driver(info.drivername);
2662 SAFE_FREE(dbuf.dptr);
2663 *info_ptr=memdup(&info, sizeof(info));
2665 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2666 sharename, info.printername, info.drivername));
2671 /****************************************************************************
2672 debugging function, dump at level 6 the struct in the logs
2673 ****************************************************************************/
2674 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2677 NT_PRINTER_INFO_LEVEL_2 *info2;
2679 DEBUG(106,("Dumping printer at level [%d]\n", level));
2685 if (printer.info_2 == NULL)
2689 info2=printer.info_2;
2691 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2692 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2693 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2694 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2695 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2696 DEBUGADD(106,("status:[%d]\n", info2->status));
2697 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2698 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2699 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2700 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2701 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2703 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2704 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2705 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2706 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2707 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2708 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2709 DEBUGADD(106,("location:[%s]\n", info2->location));
2710 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2711 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2712 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2713 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2719 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
2727 /****************************************************************************
2728 Get the parameters we can substitute in an NT print job.
2729 ****************************************************************************/
2731 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2733 NT_PRINTER_INFO_LEVEL *printer = NULL;
2735 **printername = **sharename = **portname = '\0';
2737 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2740 fstrcpy(*printername, printer->info_2->printername);
2741 fstrcpy(*sharename, printer->info_2->sharename);
2742 fstrcpy(*portname, printer->info_2->portname);
2744 free_a_printer(&printer, 2);
2747 /****************************************************************************
2748 Update the changeid time.
2749 This is SO NASTY as some drivers need this to change, others need it
2750 static. This value will change every second, and I must hope that this
2751 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
2753 ****************************************************************************/
2755 static uint32 rev_changeid(void)
2759 get_process_uptime(&tv);
2762 /* Return changeid as msec since spooler restart */
2763 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
2766 * This setting seems to work well but is too untested
2767 * to replace the above calculation. Left in for experiementation
2768 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
2770 return tv.tv_sec * 10 + tv.tv_usec / 100000;
2775 * The function below are the high level ones.
2776 * only those ones must be called from the spoolss code.
2780 /****************************************************************************
2781 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2782 ****************************************************************************/
2784 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2788 dump_a_printer(printer, level);
2795 * Update the changestamp. Emperical tests show that the
2796 * ChangeID is always updated,but c_setprinter is
2797 * global spooler variable (not per printer).
2800 /* ChangeID **must** be increasing over the lifetime
2801 of client's spoolss service in order for the
2802 client's cache to show updates */
2804 printer.info_2->changeid = rev_changeid();
2807 * Because one day someone will ask:
2808 * NT->NT An admin connection to a remote
2809 * printer show changes imeediately in
2810 * the properities dialog
2812 * A non-admin connection will only show the
2813 * changes after viewing the properites page
2814 * 2 times. Seems to be related to a
2815 * race condition in the client between the spooler
2816 * updating the local cache and the Explorer.exe GUI
2817 * actually displaying the properties.
2819 * This is fixed in Win2k. admin/non-admin
2820 * connections both display changes immediately.
2825 result=update_a_printer_2(printer.info_2);
2829 result=WERR_UNKNOWN_LEVEL;
2836 /****************************************************************************
2837 Initialize printer devmode & data with previously saved driver init values.
2838 ****************************************************************************/
2840 static BOOL set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
2844 TDB_DATA kbuf, dbuf;
2845 NT_PRINTER_PARAM *current;
2846 NT_PRINTER_INFO_LEVEL_2 info;
2849 * Delete any printer data 'specifics' already set. When called for driver
2850 * replace, there will generally be some, but during an add printer, there
2851 * should not be any (if there are delete them).
2853 while ( (current=info_ptr->specific) != NULL ) {
2854 info_ptr->specific=current->next;
2855 SAFE_FREE(current->data);
2861 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
2864 kbuf.dsize = strlen(key)+1;
2866 dbuf = tdb_fetch(tdb_drivers, kbuf);
2869 * When changing to a driver that has no init info in the tdb, remove
2870 * the previous drivers init info and leave the new on blank.
2872 free_nt_devicemode(&info_ptr->devmode);
2877 * Get the saved DEVMODE..
2879 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2882 * The saved DEVMODE contains the devicename from the printer used during
2883 * the initialization save. Change it to reflect the new printer.
2885 ZERO_STRUCT(info.devmode->devicename);
2886 fstrcpy(info.devmode->devicename, info_ptr->printername);
2890 * NT/2k does not change out the entire DeviceMode of a printer
2891 * when changing the driver. Only the driverextra, private, &
2892 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
2894 * Later e4xamination revealed that Windows NT/2k does reset the
2895 * the printer's device mode, bit **only** when you change a
2896 * property of the device mode such as the page orientation.
2903 * Bind the saved DEVMODE to the new the printer.
2905 free_nt_devicemode(&info_ptr->devmode);
2906 info_ptr->devmode = info.devmode;
2908 /* copy the entire devmode if we currently don't have one */
2910 if (!info_ptr->devmode) {
2911 DEBUG(10,("set_driver_init_2: Current Devmode is NULL. Copying entire Device Mode\n"));
2912 info_ptr->devmode = info.devmode;
2915 /* only set the necessary fields */
2917 DEBUG(10,("set_driver_init_2: Setting driverversion [0x%x] and private data [0x%x]\n",
2918 info.devmode->driverversion, info.devmode->driverextra));
2920 info_ptr->devmode->driverversion = info.devmode->driverversion;
2922 SAFE_FREE(info_ptr->devmode->private);
2923 info_ptr->devmode->private = NULL;
2925 if (info.devmode->driverversion)
2926 info_ptr->devmode->private = memdup(info.devmode->private, info.devmode->driverversion);
2928 free_nt_devicemode(&info.devmode);
2932 DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
2933 info_ptr->printername, info_ptr->drivername));
2936 * Add the printer data 'specifics' to the new printer
2938 len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len);
2940 SAFE_FREE(dbuf.dptr);
2945 /****************************************************************************
2946 Initialize printer devmode & data with previously saved driver init values.
2947 When a printer is created using AddPrinter, the drivername bound to the
2948 printer is used to lookup previously saved driver initialization info, which
2949 is bound to the new printer.
2950 ****************************************************************************/
2952 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
2954 BOOL result = False;
2959 result=set_driver_init_2(printer->info_2);
2963 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
2971 /****************************************************************************
2972 Delete driver init data stored for a specified driver
2973 ****************************************************************************/
2975 BOOL del_driver_init(char *drivername)
2980 if (!drivername || !*drivername) {
2981 DEBUG(3,("del_driver_init: No drivername specified!\n"));
2985 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
2988 kbuf.dsize = strlen(key)+1;
2990 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
2992 return (tdb_delete(tdb_drivers, kbuf) == 0);
2995 /****************************************************************************
2996 Pack up the DEVMODE and specifics for a printer into a 'driver init' entry
2997 in the tdb. Note: this is different from the driver entry and the printer
2998 entry. There should be a single driver init entry for each driver regardless
2999 of whether it was installed from NT or 2K. Technically, they should be
3000 different, but they work out to the same struct.
3001 ****************************************************************************/
3003 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3007 int buflen, len, ret;
3008 TDB_DATA kbuf, dbuf;
3015 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3017 len += pack_specifics(info->specific, buf+len, buflen-len);
3019 if (buflen != len) {
3022 tb = (char *)Realloc(buf, len);
3024 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3033 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3036 kbuf.dsize = strlen(key)+1;
3040 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3044 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3048 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n",
3049 info->sharename, info->drivername));
3054 /****************************************************************************
3055 Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer
3056 ****************************************************************************/
3058 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3062 dump_a_printer(printer, level);
3068 result=update_driver_init_2(printer.info_2);
3079 /****************************************************************************
3080 Convert the printer data value, a REG_BINARY array, into an initialization
3081 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3082 got to keep the endians happy :).
3083 ****************************************************************************/
3085 static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode)
3087 BOOL result = False;
3091 ZERO_STRUCT(devmode);
3093 prs_init(&ps, 0, ctx, UNMARSHALL);
3094 ps.data_p = (char *)param->data;
3095 ps.buffer_size = param->data_len;
3097 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3098 result = convert_devicemode("", &devmode, &nt_devmode);
3100 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3105 /****************************************************************************
3106 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3108 1. Use the driver's config DLL to this UNC printername and:
3109 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3110 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3111 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3113 The last step triggers saving the "driver initialization" information for
3114 this printer into the tdb. Later, new printers that use this driver will
3115 have this initialization information bound to them. This simulates the
3116 driver initialization, as if it had run on the Samba server (as it would
3119 The Win32 client side code requirement sucks! But until we can run arbitrary
3120 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3122 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3123 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3124 about it and you will realize why. JRR 010720
3125 ****************************************************************************/
3127 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
3129 WERROR status = WERR_OK;
3130 TALLOC_CTX *ctx = NULL;
3131 NT_DEVICEMODE *nt_devmode = NULL;
3132 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3135 * When the DEVMODE is already set on the printer, don't try to unpack it.
3138 if (!printer->info_2->devmode && param->data_len) {
3140 * Set devmode on printer info, so entire printer initialization can be
3144 if ((ctx = talloc_init()) == NULL)
3147 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3148 status = WERR_NOMEM;
3152 ZERO_STRUCTP(nt_devmode);
3155 * The DEVMODE is held in the 'data' component of the param in raw binary.
3156 * Convert it to to a devmode structure
3158 if (!convert_driver_init(param, ctx, nt_devmode)) {
3159 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3160 status = WERR_INVALID_PARAM;
3164 printer->info_2->devmode = nt_devmode;
3168 * Pack up and add (or update) the DEVMODE and any current printer data to
3169 * a 'driver init' element in the tdb
3173 if (update_driver_init(*printer, 2)!=0) {
3174 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3175 status = WERR_NOMEM;
3180 * If driver initialization info was successfully saved, set the current
3181 * printer to match it. This allows initialization of the current printer
3182 * as well as the driver.
3184 status = mod_a_printer(*printer, 2);
3185 if (!W_ERROR_IS_OK(status)) {
3186 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3187 printer->info_2->printername));
3191 srv_spoolss_sendnotify(p, handle);
3195 talloc_destroy(ctx);
3197 SAFE_FREE(nt_devmode->private);
3198 SAFE_FREE(nt_devmode);
3199 printer->info_2->devmode = tmp_devmode;
3204 /****************************************************************************
3205 Update the driver init info (DEVMODE and specifics) for a printer
3206 ****************************************************************************/
3208 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
3210 WERROR status = WERR_OK;
3216 status=save_driver_init_2(printer, param);
3220 status=WERR_UNKNOWN_LEVEL;
3227 /****************************************************************************
3228 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3229 ****************************************************************************/
3231 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
3234 NT_PRINTER_INFO_LEVEL *printer = NULL;
3238 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3244 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3245 DEBUG(0,("get_a_printer: malloc fail.\n"));
3248 ZERO_STRUCTP(printer);
3249 result=get_a_printer_2(&printer->info_2, sharename);
3250 if (W_ERROR_IS_OK(result)) {
3251 dump_a_printer(*printer, level);
3252 *pp_printer = printer;
3259 result=WERR_UNKNOWN_LEVEL;
3263 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
3268 /****************************************************************************
3269 Deletes a NT_PRINTER_INFO_LEVEL struct.
3270 ****************************************************************************/
3272 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3275 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3277 DEBUG(104,("freeing a printer at level [%d]\n", level));
3279 if (printer == NULL)
3286 if (printer->info_2 != NULL)
3288 free_nt_printer_info_level_2(&printer->info_2);
3302 SAFE_FREE(*pp_printer);
3306 /****************************************************************************
3307 ****************************************************************************/
3308 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3311 DEBUG(104,("adding a printer at level [%d]\n", level));
3312 dump_a_printer_driver(driver, level);
3318 result=add_a_printer_driver_3(driver.info_3);
3324 result=add_a_printer_driver_6(driver.info_6);
3334 /****************************************************************************
3335 ****************************************************************************/
3336 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3337 fstring drivername, fstring architecture, uint32 version)
3344 /* Sometime we just want any version of the driver */
3346 if ( version == DRIVER_ANY_VERSION ) {
3347 /* look for Win2k first and then for NT4 */
3348 result = get_a_printer_driver_3(&driver->info_3, drivername,
3351 if ( !W_ERROR_IS_OK(result) ) {
3352 result = get_a_printer_driver_3( &driver->info_3,
3353 drivername, architecture, 2 );
3357 result = get_a_printer_driver_3(&driver->info_3, drivername,
3358 architecture, version);
3367 if (W_ERROR_IS_OK(result))
3368 dump_a_printer_driver(*driver, level);
3373 /****************************************************************************
3374 ****************************************************************************/
3375 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3383 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3384 if (driver.info_3 != NULL)
3386 info3=driver.info_3;
3387 SAFE_FREE(info3->dependentfiles);
3388 ZERO_STRUCTP(info3);
3400 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3401 if (driver.info_6 != NULL)
3403 info6=driver.info_6;
3404 SAFE_FREE(info6->dependentfiles);
3405 SAFE_FREE(info6->previousnames);
3406 ZERO_STRUCTP(info6);
3424 /****************************************************************************
3425 Determine whether or not a particular driver is currently assigned
3427 ****************************************************************************/
3429 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i )
3432 int n_services = lp_numservices();
3433 NT_PRINTER_INFO_LEVEL *printer = NULL;
3438 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
3440 /* loop through the printers.tdb and check for the drivername */
3442 for (snum=0; snum<n_services; snum++)
3444 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
3447 if ( !W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) )
3450 if ( !StrCaseCmp(i->name, printer->info_2->drivername) ) {
3451 free_a_printer( &printer, 2 );
3455 free_a_printer( &printer, 2 );
3458 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
3460 /* report that the driver is not in use by default */
3466 /**********************************************************************
3467 Check to see if a ogiven file is in use by *info
3468 *********************************************************************/
3470 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
3477 if ( strequal(file, info->driverpath) )
3480 if ( strequal(file, info->datafile) )
3483 if ( strequal(file, info->configfile) )
3486 if ( strequal(file, info->helpfile) )
3489 s = (char*) info->dependentfiles;
3494 if ( strequal(file, s) )
3504 /**********************************************************************
3505 Utility function to remove the dependent file pointed to by the
3506 input parameter from the list
3507 *********************************************************************/
3509 static void trim_dependent_file( char* s )
3513 /* set p to the next character string in the list */
3515 p = s + strlen( s ) + 1;
3517 /* check to see that we have another string to copy back */
3521 /* loop over s copying characters from p to s */
3522 while ( *p!='\0' && *(p+1)!='\0' )
3526 /* add the two trailing NULL's */
3532 /**********************************************************************
3533 Check if any of the files used by src are also used by drv
3534 *********************************************************************/
3536 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
3537 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
3539 BOOL in_use = False;
3545 /* check each file. Remove it from the src structure if it overlaps */
3547 if ( drv_file_in_use(src->driverpath, drv) ) {
3549 fstrcpy( src->driverpath, "" );
3552 if ( drv_file_in_use(src->datafile, drv) ) {
3554 fstrcpy( src->datafile, "" );
3557 if ( drv_file_in_use(src->configfile, drv) ) {
3559 fstrcpy( src->configfile, "" );
3562 s = (char*)src->dependentfiles;
3567 if ( drv_file_in_use(s, drv) ) {
3569 trim_dependent_file( s );
3580 /****************************************************************************
3581 Determine whether or not a particular driver files are currently being
3582 used by any other driver.
3584 Return value is True if any files were in use by other drivers
3585 and False otherwise.
3587 Upon return, *info has been modified to only contain the driver files
3588 which are not in use
3589 ****************************************************************************/
3591 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
3596 fstring *list = NULL;
3597 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3599 /* loop over all driver versions */
3601 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
3603 for ( version=0; version<DRIVER_MAX_VERSION; version++ )
3605 /* get the list of drivers */
3608 ndrivers = get_ntdrivers(&list, info->environment, version);
3610 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
3611 ndrivers, info->environment, version));
3616 /* check each driver for overlap in files */
3618 for (i=0; i<ndrivers; i++)
3620 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
3622 ZERO_STRUCT(driver);
3624 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i],
3625 info->environment, version)) )
3631 /* check if d2 uses any files from d1 */
3632 /* only if this is a different driver than the one being deleted */
3634 if ( !strequal(info->name, driver.info_3->name)
3635 || (info->cversion != driver.info_3->cversion) )
3637 if ( trim_overlap_drv_files(info, driver.info_3) ) {
3638 free_a_printer_driver(driver, 3);
3644 free_a_printer_driver(driver, 3);
3650 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
3655 /****************************************************************************
3656 Actually delete the driver files. Make sure that
3657 printer_driver_files_in_use() return False before calling
3659 ****************************************************************************/
3661 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user )
3664 connection_struct *conn;
3671 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", i->name, i->cversion));
3674 * Connect to the print$ share under the same account as the
3675 * user connected to the rpc pipe. Note we must be root to
3680 null_pw = data_blob( NULL, 0 );
3681 conn = make_connection_with_chdir( "print$", null_pw, "A:", user->vuid, &nt_status );
3685 DEBUG(0,("delete_driver_files: Unable to connect\n"));
3689 /* Save who we are - we are temporarily becoming the connection user. */
3691 if ( !become_user(conn, conn->vuid) ) {
3692 DEBUG(0,("delete_driver_files: Can't become user!\n"));
3696 /* now delete the files; must strip the '\print$' string from
3699 if ( *i->driverpath ) {
3700 if ( (s = strchr( &i->driverpath[1], '\\' )) != NULL ) {
3701 DEBUG(10,("deleting driverfile [%s]\n", s));
3702 unlink_internals(conn, 0, s);
3706 if ( *i->configfile ) {
3707 if ( (s = strchr( &i->configfile[1], '\\' )) != NULL ) {
3708 DEBUG(10,("deleting configfile [%s]\n", s));
3709 unlink_internals(conn, 0, s);
3713 if ( *i->datafile ) {
3714 if ( (s = strchr( &i->datafile[1], '\\' )) != NULL ) {
3715 DEBUG(10,("deleting datafile [%s]\n", s));
3716 unlink_internals(conn, 0, s);
3720 if ( *i->helpfile ) {
3721 if ( (s = strchr( &i->helpfile[1], '\\' )) != NULL ) {
3722 DEBUG(10,("deleting helpfile [%s]\n", s));
3723 unlink_internals(conn, 0, s);
3727 s = (char*)i->dependentfiles;
3732 if ( (file = strchr( s+1, '\\' )) != NULL )
3734 DEBUG(10,("deleting dependent file [%s]\n", file));
3735 unlink_internals(conn, 0, file );
3736 file += strlen( file ) + 1;
3745 /****************************************************************************
3746 Remove a printer driver from the TDB. This assumes that the the driver was
3747 previously looked up.
3748 ***************************************************************************/
3750 static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user,
3751 uint32 version, BOOL delete_files )
3756 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
3758 /* delete the tdb data first */
3760 get_short_archi(arch, i->environment);
3761 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
3762 arch, version, i->name);
3764 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
3765 key, delete_files ? "TRUE" : "FALSE" ));
3768 dump_a_printer_driver( ctr, 3 );
3771 kbuf.dsize=strlen(key)+1;
3773 if (tdb_delete(tdb_drivers, kbuf) == -1) {
3774 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
3775 return WERR_ACCESS_DENIED;
3779 * now delete any associated files if delete_files == True
3780 * even if this part failes, we return succes because the
3781 * driver doesn not exist any more
3785 delete_driver_files( i, user );
3787 DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
3793 /****************************************************************************
3794 Remove a printer driver from the TDB. This assumes that the the driver was
3795 previously looked up.
3796 ***************************************************************************/
3798 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user,
3799 uint32 version, BOOL delete_files )
3804 /* see if we should delete all versions of this driver */
3806 if ( version == DRIVER_ANY_VERSION ) {
3807 for ( ver=0; ver<DRIVER_MAX_VERSION; ver++ ) {
3808 err = delete_printer_driver_internal(i, user, ver, delete_files );
3809 if ( !W_ERROR_IS_OK(err) )
3814 delete_printer_driver_internal(i, user, version, delete_files );
3820 /****************************************************************************
3821 ****************************************************************************/
3823 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
3824 fstring value, uint8 **data, uint32 *type, uint32 *len)
3826 /* right now that's enough ! */
3827 NT_PRINTER_PARAM *param;
3830 param=printer.info_2->specific;
3832 while (param != NULL && i < param_index) {
3840 /* exited because it exist */
3842 StrnCpy(value, param->value, sizeof(fstring)-1);
3843 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3846 ZERO_STRUCTP(*data);
3847 memcpy(*data, param->data, param->data_len);
3848 *len=param->data_len;
3852 /****************************************************************************
3853 ****************************************************************************/
3854 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
3855 fstring value, uint8 **data, uint32 *type, uint32 *len)
3857 /* right now that's enough ! */
3858 NT_PRINTER_PARAM *param;
3860 DEBUG(10, ("get_specific_param\n"));
3862 param=printer.info_2->specific;
3864 while (param != NULL)
3866 #if 1 /* JRA - I think this should be case insensitive.... */
3867 if ( strequal(value, param->value)
3869 if ( !strcmp(value, param->value)
3871 && strlen(value)==strlen(param->value))
3879 DEBUGADD(10, ("get_specific_param: found one param\n"));
3880 /* exited because it exist */
3883 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3886 memcpy(*data, param->data, param->data_len);
3887 *len=param->data_len;
3889 DEBUGADD(10, ("get_specific_param: exit true\n"));
3892 DEBUGADD(10, ("get_specific_param: exit false\n"));
3896 /****************************************************************************
3897 Store a security desc for a printer.
3898 ****************************************************************************/
3900 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
3902 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3903 SEC_DESC_BUF *old_secdesc_ctr = NULL;
3905 TALLOC_CTX *mem_ctx = NULL;
3909 mem_ctx = talloc_init();
3910 if (mem_ctx == NULL)
3913 /* The old owner and group sids of the security descriptor are not
3914 present when new ACEs are added or removed by changing printer
3915 permissions through NT. If they are NULL in the new security
3916 descriptor then copy them over from the old one. */
3918 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3919 DOM_SID *owner_sid, *group_sid;
3920 SEC_ACL *dacl, *sacl;
3921 SEC_DESC *psd = NULL;
3924 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3926 /* Pick out correct owner and group sids */
3928 owner_sid = secdesc_ctr->sec->owner_sid ?
3929 secdesc_ctr->sec->owner_sid :
3930 old_secdesc_ctr->sec->owner_sid;
3932 group_sid = secdesc_ctr->sec->grp_sid ?
3933 secdesc_ctr->sec->grp_sid :
3934 old_secdesc_ctr->sec->grp_sid;
3936 dacl = secdesc_ctr->sec->dacl ?
3937 secdesc_ctr->sec->dacl :
3938 old_secdesc_ctr->sec->dacl;
3940 sacl = secdesc_ctr->sec->sacl ?
3941 secdesc_ctr->sec->sacl :
3942 old_secdesc_ctr->sec->sacl;
3944 /* Make a deep copy of the security descriptor */
3946 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3947 owner_sid, group_sid,
3952 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3955 if (!new_secdesc_ctr) {
3956 new_secdesc_ctr = secdesc_ctr;
3959 /* Store the security descriptor in a tdb */
3961 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3962 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3964 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3966 status = WERR_BADFUNC;
3970 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3972 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
3975 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3976 status = WERR_BADFUNC;
3979 /* Free malloc'ed memory */
3985 talloc_destroy(mem_ctx);
3989 /****************************************************************************
3990 Construct a default security descriptor buffer for a printer.
3991 ****************************************************************************/
3993 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3997 SEC_ACL *psa = NULL;
3998 SEC_DESC_BUF *sdb = NULL;
3999 SEC_DESC *psd = NULL;
4003 /* Create an ACE where Everyone is allowed to print */
4005 init_sec_access(&sa, PRINTER_ACE_PRINT);
4006 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4007 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4009 /* Make the security descriptor owned by the Administrators group
4010 on the PDC of the domain. */
4012 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4013 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4016 /* Backup plan - make printer owned by admins.
4017 This should emulate a lanman printer as security
4018 settings can't be changed. */
4020 sid_copy(&owner_sid, get_global_sam_sid());
4021 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4024 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4025 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4026 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4027 SEC_ACE_FLAG_INHERIT_ONLY);
4029 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4030 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4031 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4033 /* The ACL revision number in rpc_secdesc.h differs from the one
4034 created by NT when setting ACE entries in printer
4035 descriptors. NT4 complains about the property being edited by a
4038 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4039 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
4041 NULL, psa, &sd_size);
4045 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4049 sdb = make_sec_desc_buf(ctx, sd_size, psd);
4051 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4052 (unsigned int)sd_size));
4057 /****************************************************************************
4058 Get a security desc for a printer.
4059 ****************************************************************************/
4061 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4067 if ((temp = strchr(printername + 2, '\\'))) {
4068 printername = temp + 1;
4071 /* Fetch security descriptor from tdb */
4073 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4075 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4076 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4078 DEBUG(4,("using default secdesc for %s\n", printername));
4080 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4084 /* Save default security descriptor for later */
4086 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4087 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4089 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4090 tdb_prs_store(tdb_printers, key, &ps);
4097 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4098 this security descriptor has been created when winbindd was
4099 down. Take ownership of security descriptor. */
4101 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4104 /* Change sd owner to workgroup administrator */
4106 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4107 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4108 SEC_DESC *psd = NULL;
4113 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4115 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
4117 (*secdesc_ctr)->sec->grp_sid,
4118 (*secdesc_ctr)->sec->sacl,
4119 (*secdesc_ctr)->sec->dacl,
4122 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4124 /* Swap with other one */
4126 *secdesc_ctr = new_secdesc_ctr;
4130 nt_printing_setsec(printername, *secdesc_ctr);
4134 if (DEBUGLEVEL >= 10) {
4135 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4138 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4139 printername, the_acl->num_aces));
4141 for (i = 0; i < the_acl->num_aces; i++) {
4144 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4146 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4147 the_acl->ace[i].type, the_acl->ace[i].flags,
4148 the_acl->ace[i].info.mask));
4158 1: level not implemented
4159 2: file doesn't exist
4160 3: can't allocate memory
4161 4: can't free memory
4162 5: non existant struct
4166 A printer and a printer driver are 2 different things.
4167 NT manages them separatelly, Samba does the same.
4168 Why ? Simply because it's easier and it makes sense !
4170 Now explanation: You have 3 printers behind your samba server,
4171 2 of them are the same make and model (laser A and B). But laser B
4172 has an 3000 sheet feeder and laser A doesn't such an option.
4173 Your third printer is an old dot-matrix model for the accounting :-).
4175 If the /usr/local/samba/lib directory (default dir), you will have
4176 5 files to describe all of this.
4178 3 files for the printers (1 by printer):
4181 NTprinter_accounting
4182 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4183 NTdriver_printer model X
4184 NTdriver_printer model Y
4186 jfm: I should use this comment for the text file to explain
4187 same thing for the forms BTW.
4188 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4192 /* Convert generic access rights to printer object specific access rights.
4193 It turns out that NT4 security descriptors use generic access rights and
4194 NT5 the object specific ones. */
4196 void map_printer_permissions(SEC_DESC *sd)
4200 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4201 se_map_generic(&sd->dacl->ace[i].info.mask,
4202 &printer_generic_mapping);
4206 /****************************************************************************
4207 Check a user has permissions to perform the given operation. We use the
4208 permission constants defined in include/rpc_spoolss.h to check the various
4209 actions we perform when checking printer access.
4211 PRINTER_ACCESS_ADMINISTER:
4212 print_queue_pause, print_queue_resume, update_printer_sec,
4213 update_printer, spoolss_addprinterex_level_2,
4214 _spoolss_setprinterdata
4219 JOB_ACCESS_ADMINISTER:
4220 print_job_delete, print_job_pause, print_job_resume,
4223 ****************************************************************************/
4224 BOOL print_access_check(struct current_user *user, int snum, int access_type)
4226 SEC_DESC_BUF *secdesc = NULL;
4227 uint32 access_granted;
4231 TALLOC_CTX *mem_ctx = NULL;
4232 extern struct current_user current_user;
4234 /* If user is NULL then use the current_user structure */
4237 user = ¤t_user;
4239 /* Always allow root or printer admins to do anything */
4241 if (user->uid == 0 ||
4242 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
4246 /* Get printer name */
4248 pname = PRINTERNAME(snum);
4250 if (!pname || !*pname) {
4255 /* Get printer security descriptor */
4257 if(!(mem_ctx = talloc_init())) {
4262 nt_printing_getsec(mem_ctx, pname, &secdesc);
4264 if (access_type == JOB_ACCESS_ADMINISTER) {
4265 SEC_DESC_BUF *parent_secdesc = secdesc;
4267 /* Create a child security descriptor to check permissions
4268 against. This is because print jobs are child objects
4269 objects of a printer. */
4271 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4273 /* Now this is the bit that really confuses me. The access
4274 type needs to be changed from JOB_ACCESS_ADMINISTER to
4275 PRINTER_ACCESS_ADMINISTER for this to work. Something
4276 to do with the child (job) object becoming like a
4279 access_type = PRINTER_ACCESS_ADMINISTER;
4284 map_printer_permissions(secdesc->sec);
4286 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4287 &access_granted, &status);
4289 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4291 talloc_destroy(mem_ctx);
4299 /****************************************************************************
4300 Check the time parameters allow a print operation.
4301 *****************************************************************************/
4303 BOOL print_time_access_check(int snum)
4305 NT_PRINTER_INFO_LEVEL *printer = NULL;
4307 time_t now = time(NULL);
4311 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4314 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
4318 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4320 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
4323 free_a_printer(&printer, 2);
4331 #if 0 /* JERRY - not used */
4332 /****************************************************************************
4333 Attempt to write a default device.
4334 *****************************************************************************/
4336 WERROR printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
4338 NT_PRINTER_INFO_LEVEL *printer = NULL;
4342 * Don't bother if no default devicemode was sent.
4345 if (printer_default->devmode_cont.devmode == NULL)
4348 result = get_a_printer(&printer, 2, lp_servicename(snum));
4349 if (!W_ERROR_IS_OK(result)) return result;
4352 * Just ignore it if we already have a devmode.
4355 if (printer->info_2->devmode != NULL)
4359 * We don't have a devicemode and we're trying to write
4360 * one. Check we have the access needed.
4362 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
4364 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
4365 PRINTER_ACCESS_ADMINISTER) {
4366 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
4367 result = WERR_ACCESS_DENIED;
4371 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4372 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
4373 lp_servicename(snum) ));
4374 result = WERR_ACCESS_DENIED;
4375 /*result = NT_STATUS_NO_PROBLEMO;*/
4379 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
4382 * Convert the on the wire devicemode format to the internal one.
4385 if (!convert_devicemode(printer->info_2->printername,
4386 printer_default->devmode_cont.devmode,
4387 &printer->info_2->devmode)) {
4388 result = WERR_NOMEM;
4393 * Finally write back to the tdb.
4396 result = mod_a_printer(*printer, 2);
4400 free_a_printer(&printer, 2);