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-2003.
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 const 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 SAFE_FREE(dbuf.dptr);
216 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
219 if (tdb_delete(tdb_drivers, kbuf) != 0) {
220 SAFE_FREE(dbuf.dptr);
221 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
226 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
227 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
228 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
229 SAFE_FREE(dbuf.dptr);
230 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
233 if (tdb_delete(tdb_drivers, kbuf) != 0) {
234 SAFE_FREE(dbuf.dptr);
235 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
240 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
241 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
242 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
243 SAFE_FREE(dbuf.dptr);
244 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
247 if (tdb_delete(tdb_drivers, kbuf) != 0) {
248 SAFE_FREE(dbuf.dptr);
249 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
254 SAFE_FREE(dbuf.dptr);
260 /****************************************************************************
261 Open the NT printing tdbs. Done once before fork().
262 ****************************************************************************/
264 BOOL nt_printing_init(void)
266 static pid_t local_pid;
267 const char *vstring = "INFO/version";
269 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
273 tdb_close(tdb_drivers);
274 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
276 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
277 lock_path("ntdrivers.tdb"), strerror(errno) ));
282 tdb_close(tdb_printers);
283 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
285 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
286 lock_path("ntprinters.tdb"), strerror(errno) ));
291 tdb_close(tdb_forms);
292 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
294 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
295 lock_path("ntforms.tdb"), strerror(errno) ));
299 local_pid = sys_getpid();
301 /* handle a Samba upgrade */
302 tdb_lock_bystring(tdb_drivers, vstring, 0);
306 /* Cope with byte-reversed older versions of the db. */
307 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
308 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
309 /* Written on a bigendian machine with old fetch_int code. Save as le. */
310 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
311 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
312 vers_id = NTDRIVERS_DATABASE_VERSION;
315 if (vers_id != NTDRIVERS_DATABASE_VERSION) {
317 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
318 if (!upgrade_to_version_3())
321 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
323 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
326 tdb_unlock_bystring(tdb_drivers, vstring);
328 update_c_setprinter(True);
331 * register callback to handle updating printers as new
332 * drivers are installed
335 message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
338 * register callback to handle updating printer data
339 * when a driver is initialized
342 message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
348 /*******************************************************************
349 tdb traversal function for counting printers.
350 ********************************************************************/
352 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
353 TDB_DATA data, void *context)
355 int *printer_count = (int*)context;
357 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
359 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
365 /*******************************************************************
366 Update the spooler global c_setprinter. This variable is initialized
367 when the parent smbd starts with the number of existing printers. It
368 is monotonically increased by the current number of printers *after*
369 each add or delete printer RPC. Only Microsoft knows why... JRR020119
370 ********************************************************************/
372 uint32 update_c_setprinter(BOOL initialize)
375 int32 printer_count = 0;
377 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
379 /* Traverse the tdb, counting the printers */
380 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
382 /* If initializing, set c_setprinter to current printers count
383 * otherwise, bump it by the current printer count
386 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
388 c_setprinter = printer_count;
390 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
391 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
393 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
395 return (uint32)c_setprinter;
398 /*******************************************************************
399 Get the spooler global c_setprinter, accounting for initialization.
400 ********************************************************************/
402 uint32 get_c_setprinter(void)
404 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
406 if (c_setprinter == (int32)-1)
407 c_setprinter = update_c_setprinter(True);
409 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
411 return (uint32)c_setprinter;
414 /****************************************************************************
415 Get builtin form struct list.
416 ****************************************************************************/
418 int get_builtin_ntforms(nt_forms_struct **list)
420 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
421 return sizeof(default_forms) / sizeof(default_forms[0]);
424 /****************************************************************************
425 get a builtin form struct
426 ****************************************************************************/
428 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
432 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
433 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
434 count = sizeof(default_forms) / sizeof(default_forms[0]);
435 for (i=0;i<count;i++) {
436 if (strequal(form_name,default_forms[i].name)) {
437 DEBUGADD(6,("Found builtin form %s \n", form_name));
438 memcpy(form,&default_forms[i],sizeof(*form));
446 /****************************************************************************
447 get a form struct list
448 ****************************************************************************/
449 int get_ntforms(nt_forms_struct **list)
451 TDB_DATA kbuf, newkey, dbuf;
453 nt_forms_struct form;
458 for (kbuf = tdb_firstkey(tdb_forms);
460 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
462 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
465 dbuf = tdb_fetch(tdb_forms, kbuf);
469 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
470 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
471 &i, &form.flag, &form.width, &form.length, &form.left,
472 &form.top, &form.right, &form.bottom);
473 SAFE_FREE(dbuf.dptr);
474 if (ret != dbuf.dsize)
477 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
479 DEBUG(0,("get_ntforms: Realloc fail.\n"));
491 /****************************************************************************
492 write a form struct list
493 ****************************************************************************/
494 int write_ntforms(nt_forms_struct **list, int number)
501 for (i=0;i<number;i++) {
502 /* save index, so list is rebuilt in correct order */
503 len = tdb_pack(buf, sizeof(buf), "dddddddd",
504 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
505 (*list)[i].left, (*list)[i].top, (*list)[i].right,
507 if (len > sizeof(buf)) break;
508 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
509 kbuf.dsize = strlen(key)+1;
513 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
519 /****************************************************************************
520 add a form struct at the end of the list
521 ****************************************************************************/
522 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
530 * NT tries to add forms even when
531 * they are already in the base
532 * only update the values if already present
537 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
538 for (n=0; n<*count; n++) {
539 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
540 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
547 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
548 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
552 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
556 (*list)[n].flag=form->flags;
557 (*list)[n].width=form->size_x;
558 (*list)[n].length=form->size_y;
559 (*list)[n].left=form->left;
560 (*list)[n].top=form->top;
561 (*list)[n].right=form->right;
562 (*list)[n].bottom=form->bottom;
567 /****************************************************************************
568 Delete a named form struct.
569 ****************************************************************************/
571 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
580 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
582 for (n=0; n<*count; n++) {
583 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
584 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
590 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
591 *ret = WERR_INVALID_PARAM;
595 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
596 kbuf.dsize = strlen(key)+1;
598 if (tdb_delete(tdb_forms, kbuf) != 0) {
606 /****************************************************************************
607 Update a form struct.
608 ****************************************************************************/
610 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
614 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
616 DEBUG(106, ("[%s]\n", form_name));
617 for (n=0; n<count; n++) {
618 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
619 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
623 if (n==count) return;
625 (*list)[n].flag=form->flags;
626 (*list)[n].width=form->size_x;
627 (*list)[n].length=form->size_y;
628 (*list)[n].left=form->left;
629 (*list)[n].top=form->top;
630 (*list)[n].right=form->right;
631 (*list)[n].bottom=form->bottom;
634 /****************************************************************************
635 Get the nt drivers list.
636 Traverse the database and look-up the matching names.
637 ****************************************************************************/
638 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
644 TDB_DATA kbuf, newkey;
646 get_short_archi(short_archi, architecture);
647 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
649 for (kbuf = tdb_firstkey(tdb_drivers);
651 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
653 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
656 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
657 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
662 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
669 /****************************************************************************
670 Function to do the mapping between the long architecture name and
672 ****************************************************************************/
673 BOOL get_short_archi(char *short_archi, const char *long_archi)
676 const char *long_archi;
677 const char *short_archi;
680 struct table archi_table[]=
682 {"Windows 4.0", "WIN40" },
683 {"Windows NT x86", "W32X86" },
684 {"Windows NT R4000", "W32MIPS" },
685 {"Windows NT Alpha_AXP", "W32ALPHA" },
686 {"Windows NT PowerPC", "W32PPC" },
692 DEBUG(107,("Getting architecture dependant directory\n"));
694 if (long_archi == NULL) {
695 DEBUGADD(107,("Bad long_archi param.!\n"));
701 } while ( (archi_table[i].long_archi!=NULL ) &&
702 StrCaseCmp(long_archi, archi_table[i].long_archi) );
704 if (archi_table[i].long_archi==NULL) {
705 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
709 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
711 DEBUGADD(108,("index: [%d]\n", i));
712 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
713 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
718 /****************************************************************************
719 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
720 There are two case to be covered here: PE (Portable Executable) and NE (New
721 Executable) files. Both files support the same INFO structure, but PE files
722 store the signature in unicode, and NE files store it as !unicode.
723 returns -1 on error, 1 on version info found, and 0 on no version info found.
724 ****************************************************************************/
726 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
732 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
733 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
734 fname, PE_HEADER_SIZE));
738 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
739 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
740 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
742 goto no_version_info;
745 /* Is this really a DOS header? */
746 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
747 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
748 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
749 goto no_version_info;
752 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
753 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
754 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
756 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
757 goto no_version_info;
760 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
761 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
763 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
764 goto no_version_info;
767 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
768 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
770 int section_table_bytes;
772 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
773 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
774 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
775 /* At this point, we assume the file is in error. It still could be somthing
776 * else besides a PE file, but it unlikely at this point.
781 /* get the section table */
782 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
783 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
785 if ((buf=malloc(section_table_bytes)) == NULL) {
786 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
787 fname, section_table_bytes));
791 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
792 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
797 /* Iterate the section table looking for the resource section ".rsrc" */
798 for (i = 0; i < num_sections; i++) {
799 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
801 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
802 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
803 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
806 if ((buf=malloc(section_bytes)) == NULL) {
807 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
808 fname, section_bytes));
812 /* Seek to the start of the .rsrc section info */
813 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
814 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
819 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
820 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
825 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
826 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
827 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
828 /* Align to next long address */
829 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
831 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
832 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
833 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
835 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
836 fname, *major, *minor,
837 (*major>>16)&0xffff, *major&0xffff,
838 (*minor>>16)&0xffff, *minor&0xffff));
847 /* Version info not found, fall back to origin date/time */
848 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
852 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
853 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
854 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
855 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
856 /* At this point, we assume the file is in error. It still could be somthing
857 * else besides a NE file, but it unlikely at this point. */
861 /* Allocate a bit more space to speed up things */
863 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
864 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
865 fname, PE_HEADER_SIZE));
869 /* This is a HACK! I got tired of trying to sort through the messy
870 * 'NE' file format. If anyone wants to clean this up please have at
871 * it, but this works. 'NE' files will eventually fade away. JRR */
872 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
873 /* Cover case that should not occur in a well formed 'NE' .dll file */
874 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
876 for(i=0; i<byte_count; i++) {
877 /* Fast skip past data that can't possibly match */
878 if (buf[i] != 'V') continue;
880 /* Potential match data crosses buf boundry, move it to beginning
881 * of buf, and fill the buf with as much as it will hold. */
882 if (i>byte_count-VS_VERSION_INFO_SIZE) {
885 memcpy(buf, &buf[i], byte_count-i);
886 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
887 (byte_count-i))) < 0) {
889 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
894 byte_count = bc + (byte_count - i);
895 if (byte_count<VS_VERSION_INFO_SIZE) break;
900 /* Check that the full signature string and the magic number that
901 * follows exist (not a perfect solution, but the chances that this
902 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
903 * twice, as it is simpler to read the code. */
904 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
905 /* Compute skip alignment to next long address */
906 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
907 sizeof(VS_SIGNATURE)) & 3;
908 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
910 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
911 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
912 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
913 fname, *major, *minor,
914 (*major>>16)&0xffff, *major&0xffff,
915 (*minor>>16)&0xffff, *minor&0xffff));
922 /* Version info not found, fall back to origin date/time */
923 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
928 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
929 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
930 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
941 /****************************************************************************
942 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
943 share one or more files. During the MS installation process files are checked
944 to insure that only a newer version of a shared file is installed over an
945 older version. There are several possibilities for this comparison. If there
946 is no previous version, the new one is newer (obviously). If either file is
947 missing the version info structure, compare the creation date (on Unix use
948 the modification date). Otherwise chose the numerically larger version number.
949 ****************************************************************************/
951 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
953 BOOL use_version = True;
958 time_t new_create_time;
962 time_t old_create_time;
966 files_struct *fsp = NULL;
968 SMB_STRUCT_STAT stat_buf;
972 ZERO_STRUCT(stat_buf);
973 new_create_time = (time_t)0;
974 old_create_time = (time_t)0;
976 /* Get file version info (if available) for previous file (if it exists) */
977 pstrcpy(filepath, old_file);
979 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
981 fsp = open_file_shared(conn, filepath, &stat_buf,
982 SET_OPEN_MODE(DOS_OPEN_RDONLY),
983 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
984 0, 0, &access_mode, &action);
986 /* Old file not found, so by definition new file is in fact newer */
987 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
992 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
993 if (ret == -1) goto error_exit;
996 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
999 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1000 old_create_time = st.st_mtime;
1001 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1004 close_file(fsp, True);
1006 /* Get file version info (if available) for new file */
1007 pstrcpy(filepath, new_file);
1008 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1010 fsp = open_file_shared(conn, filepath, &stat_buf,
1011 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1012 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1013 0, 0, &access_mode, &action);
1015 /* New file not found, this shouldn't occur if the caller did its job */
1016 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1021 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1022 if (ret == -1) goto error_exit;
1025 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1027 use_version = False;
1028 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1029 new_create_time = st.st_mtime;
1030 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1033 close_file(fsp, True);
1035 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1036 /* Compare versions and choose the larger version number */
1037 if (new_major > old_major ||
1038 (new_major == old_major && new_minor > old_minor)) {
1040 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1044 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1049 /* Compare modification time/dates and choose the newest time/date */
1050 if (new_create_time > old_create_time) {
1051 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1055 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1062 close_file(fsp, True);
1066 /****************************************************************************
1067 Determine the correct cVersion associated with an architecture and driver
1068 ****************************************************************************/
1069 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
1070 struct current_user *user, WERROR *perr)
1079 files_struct *fsp = NULL;
1082 connection_struct *conn;
1086 *perr = WERR_INVALID_PARAM;
1088 /* If architecture is Windows 95/98/ME, the version is always 0. */
1089 if (strcmp(architecture, "WIN40") == 0) {
1090 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1096 * Connect to the print$ share under the same account as the user connected
1097 * to the rpc pipe. Note we must still be root to do this.
1100 /* Null password is ok - we are already an authenticated user... */
1101 null_pw = data_blob(NULL, 0);
1102 fstrcpy(res_type, "A:");
1104 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1108 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1109 *perr = ntstatus_to_werror(nt_status);
1113 /* We are temporarily becoming the connection user. */
1114 if (!become_user(conn, conn->vuid)) {
1115 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1116 *perr = WERR_ACCESS_DENIED;
1120 /* Open the driver file (Portable Executable format) and determine the
1121 * deriver the cversion. */
1122 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1124 unix_convert(driverpath,conn,NULL,&bad_path,&st);
1126 fsp = open_file_shared(conn, driverpath, &st,
1127 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1128 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1129 0, 0, &access_mode, &action);
1131 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1132 driverpath, errno));
1133 *perr = WERR_ACCESS_DENIED;
1139 int ret = get_file_version(fsp, driverpath, &major, &minor);
1140 if (ret == -1) goto error_exit;
1143 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1148 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1149 * for more details. Version in this case is not just the version of the
1150 * file, but the version in the sense of kernal mode (2) vs. user mode
1151 * (3) drivers. Other bits of the version fields are the version info.
1154 cversion = major & 0x0000ffff;
1156 case 2: /* WinNT drivers */
1157 case 3: /* Win2K drivers */
1161 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1162 driverpath, cversion));
1166 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1167 driverpath, major, minor));
1170 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1171 driverpath, cversion));
1173 close_file(fsp, True);
1174 close_cnum(conn, user->vuid);
1183 close_file(fsp, True);
1185 close_cnum(conn, user->vuid);
1190 /****************************************************************************
1191 ****************************************************************************/
1192 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1193 struct current_user *user)
1195 fstring architecture;
1201 /* clean up the driver name.
1202 * we can get .\driver.dll
1203 * or worse c:\windows\system\driver.dll !
1205 /* using an intermediate string to not have overlaping memcpy()'s */
1206 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1207 fstrcpy(new_name, p+1);
1208 fstrcpy(driver->driverpath, new_name);
1211 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1212 fstrcpy(new_name, p+1);
1213 fstrcpy(driver->datafile, new_name);
1216 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1217 fstrcpy(new_name, p+1);
1218 fstrcpy(driver->configfile, new_name);
1221 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1222 fstrcpy(new_name, p+1);
1223 fstrcpy(driver->helpfile, new_name);
1226 if (driver->dependentfiles) {
1227 for (i=0; *driver->dependentfiles[i]; i++) {
1228 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1229 fstrcpy(new_name, p+1);
1230 fstrcpy(driver->dependentfiles[i], new_name);
1235 get_short_archi(architecture, driver->environment);
1237 /* jfm:7/16/2000 the client always sends the cversion=0.
1238 * The server should check which version the driver is by reading
1239 * the PE header of driver->driverpath.
1241 * For Windows 95/98 the version is 0 (so the value sent is correct)
1242 * For Windows NT (the architecture doesn't matter)
1243 * NT 3.1: cversion=0
1244 * NT 3.5/3.51: cversion=1
1248 if ((driver->cversion = get_correct_cversion( architecture,
1249 driver->driverpath, user, &err)) == -1)
1255 /****************************************************************************
1256 ****************************************************************************/
1257 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1259 fstring architecture;
1265 /* clean up the driver name.
1266 * we can get .\driver.dll
1267 * or worse c:\windows\system\driver.dll !
1269 /* using an intermediate string to not have overlaping memcpy()'s */
1270 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1271 fstrcpy(new_name, p+1);
1272 fstrcpy(driver->driverpath, new_name);
1275 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1276 fstrcpy(new_name, p+1);
1277 fstrcpy(driver->datafile, new_name);
1280 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1281 fstrcpy(new_name, p+1);
1282 fstrcpy(driver->configfile, new_name);
1285 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1286 fstrcpy(new_name, p+1);
1287 fstrcpy(driver->helpfile, new_name);
1290 if (driver->dependentfiles) {
1291 for (i=0; *driver->dependentfiles[i]; i++) {
1292 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1293 fstrcpy(new_name, p+1);
1294 fstrcpy(driver->dependentfiles[i], new_name);
1299 get_short_archi(architecture, driver->environment);
1301 /* jfm:7/16/2000 the client always sends the cversion=0.
1302 * The server should check which version the driver is by reading
1303 * the PE header of driver->driverpath.
1305 * For Windows 95/98 the version is 0 (so the value sent is correct)
1306 * For Windows NT (the architecture doesn't matter)
1307 * NT 3.1: cversion=0
1308 * NT 3.5/3.51: cversion=1
1312 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1318 /****************************************************************************
1319 ****************************************************************************/
1320 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1321 uint32 level, struct current_user *user)
1326 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1327 driver=driver_abstract.info_3;
1328 return clean_up_driver_struct_level_3(driver, user);
1332 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1333 driver=driver_abstract.info_6;
1334 return clean_up_driver_struct_level_6(driver, user);
1337 return WERR_INVALID_PARAM;
1341 /****************************************************************************
1342 This function sucks and should be replaced. JRA.
1343 ****************************************************************************/
1345 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1347 dst->cversion = src->version;
1349 fstrcpy( dst->name, src->name);
1350 fstrcpy( dst->environment, src->environment);
1351 fstrcpy( dst->driverpath, src->driverpath);
1352 fstrcpy( dst->datafile, src->datafile);
1353 fstrcpy( dst->configfile, src->configfile);
1354 fstrcpy( dst->helpfile, src->helpfile);
1355 fstrcpy( dst->monitorname, src->monitorname);
1356 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1357 dst->dependentfiles = src->dependentfiles;
1360 #if 0 /* Debugging function */
1362 static char* ffmt(unsigned char *c){
1364 static char ffmt_str[17];
1366 for (i=0; i<16; i++) {
1367 if ((c[i] < ' ') || (c[i] > '~'))
1378 /****************************************************************************
1379 ****************************************************************************/
1380 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1381 struct current_user *user, WERROR *perr)
1383 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1384 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1385 fstring architecture;
1390 connection_struct *conn;
1398 memset(inbuf, '\0', sizeof(inbuf));
1399 memset(outbuf, '\0', sizeof(outbuf));
1403 driver=driver_abstract.info_3;
1404 else if (level==6) {
1405 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1406 driver = &converted_driver;
1408 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1412 get_short_archi(architecture, driver->environment);
1415 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1416 * Note we must be root to do this.
1419 null_pw = data_blob(NULL, 0);
1420 fstrcpy(res_type, "A:");
1422 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1426 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1427 *perr = ntstatus_to_werror(nt_status);
1432 * Save who we are - we are temporarily becoming the connection user.
1435 if (!become_user(conn, conn->vuid)) {
1436 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1441 * make the directories version and version\driver_name
1442 * under the architecture directory.
1444 DEBUG(5,("Creating first directory\n"));
1445 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1446 mkdir_internal(conn, new_dir);
1448 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1449 * listed for this driver which has already been moved, skip it (note:
1450 * drivers may list the same file name several times. Then check if the
1451 * file already exists in archi\cversion\, if so, check that the version
1452 * info (or time stamps if version info is unavailable) is newer (or the
1453 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1454 * Otherwise, delete the file.
1456 * If a file is not moved to archi\cversion\ because of an error, all the
1457 * rest of the 'unmoved' driver files are removed from archi\. If one or
1458 * more of the driver's files was already moved to archi\cversion\, it
1459 * potentially leaves the driver in a partially updated state. Version
1460 * trauma will most likely occur if an client attempts to use any printer
1461 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1462 * done is appropriate... later JRR
1465 DEBUG(5,("Moving files now !\n"));
1467 if (driver->driverpath && strlen(driver->driverpath)) {
1468 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1469 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1470 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1472 status = rename_internals(conn, new_name, old_name, True);
1473 if (!NT_STATUS_IS_OK(status)) {
1474 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1475 new_name, old_name));
1476 *perr = ntstatus_to_werror(status);
1477 unlink_internals(conn, 0, new_name);
1482 unlink_internals(conn, 0, new_name);
1485 if (driver->datafile && strlen(driver->datafile)) {
1486 if (!strequal(driver->datafile, driver->driverpath)) {
1487 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1488 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1489 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1491 status = rename_internals(conn, new_name, old_name, True);
1492 if (!NT_STATUS_IS_OK(status)) {
1493 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1494 new_name, old_name));
1495 *perr = ntstatus_to_werror(status);
1496 unlink_internals(conn, 0, new_name);
1501 unlink_internals(conn, 0, new_name);
1505 if (driver->configfile && strlen(driver->configfile)) {
1506 if (!strequal(driver->configfile, driver->driverpath) &&
1507 !strequal(driver->configfile, driver->datafile)) {
1508 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1509 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1510 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1512 status = rename_internals(conn, new_name, old_name, True);
1513 if (!NT_STATUS_IS_OK(status)) {
1514 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1515 new_name, old_name));
1516 *perr = ntstatus_to_werror(status);
1517 unlink_internals(conn, 0, new_name);
1522 unlink_internals(conn, 0, new_name);
1526 if (driver->helpfile && strlen(driver->helpfile)) {
1527 if (!strequal(driver->helpfile, driver->driverpath) &&
1528 !strequal(driver->helpfile, driver->datafile) &&
1529 !strequal(driver->helpfile, driver->configfile)) {
1530 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1531 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1532 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1534 status = rename_internals(conn, new_name, old_name, True);
1535 if (!NT_STATUS_IS_OK(status)) {
1536 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1537 new_name, old_name));
1538 *perr = ntstatus_to_werror(status);
1539 unlink_internals(conn, 0, new_name);
1544 unlink_internals(conn, 0, new_name);
1548 if (driver->dependentfiles) {
1549 for (i=0; *driver->dependentfiles[i]; i++) {
1550 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1551 !strequal(driver->dependentfiles[i], driver->datafile) &&
1552 !strequal(driver->dependentfiles[i], driver->configfile) &&
1553 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1555 for (j=0; j < i; j++) {
1556 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1561 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1562 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1563 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1565 status = rename_internals(conn, new_name, old_name, True);
1566 if (!NT_STATUS_IS_OK(status)) {
1567 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1568 new_name, old_name));
1569 *perr = ntstatus_to_werror(status);
1570 unlink_internals(conn, 0, new_name);
1575 unlink_internals(conn, 0, new_name);
1581 close_cnum(conn, user->vuid);
1584 return ver == -1 ? False : True;
1587 /****************************************************************************
1588 ****************************************************************************/
1589 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1592 fstring architecture;
1598 TDB_DATA kbuf, dbuf;
1600 get_short_archi(architecture, driver->environment);
1602 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1603 * \\server is added in the rpc server layer.
1604 * It does make sense to NOT store the server's name in the printer TDB.
1607 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1609 /* .inf files do not always list a file for each of the four standard files.
1610 * Don't prepend a path to a null filename, or client claims:
1611 * "The server on which the printer resides does not have a suitable
1612 * <printer driver name> printer driver installed. Click OK if you
1613 * wish to install the driver on your local machine."
1615 if (strlen(driver->driverpath)) {
1616 fstrcpy(temp_name, driver->driverpath);
1617 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1620 if (strlen(driver->datafile)) {
1621 fstrcpy(temp_name, driver->datafile);
1622 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1625 if (strlen(driver->configfile)) {
1626 fstrcpy(temp_name, driver->configfile);
1627 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1630 if (strlen(driver->helpfile)) {
1631 fstrcpy(temp_name, driver->helpfile);
1632 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1635 if (driver->dependentfiles) {
1636 for (i=0; *driver->dependentfiles[i]; i++) {
1637 fstrcpy(temp_name, driver->dependentfiles[i]);
1638 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1642 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1644 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1651 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1654 driver->environment,
1659 driver->monitorname,
1660 driver->defaultdatatype);
1662 if (driver->dependentfiles) {
1663 for (i=0; *driver->dependentfiles[i]; i++) {
1664 len += tdb_pack(buf+len, buflen-len, "f",
1665 driver->dependentfiles[i]);
1669 if (len != buflen) {
1672 tb = (char *)Realloc(buf, len);
1674 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1685 kbuf.dsize = strlen(key)+1;
1689 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1693 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1699 /****************************************************************************
1700 ****************************************************************************/
1701 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1703 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1706 info3.cversion = driver->version;
1707 fstrcpy(info3.name,driver->name);
1708 fstrcpy(info3.environment,driver->environment);
1709 fstrcpy(info3.driverpath,driver->driverpath);
1710 fstrcpy(info3.datafile,driver->datafile);
1711 fstrcpy(info3.configfile,driver->configfile);
1712 fstrcpy(info3.helpfile,driver->helpfile);
1713 fstrcpy(info3.monitorname,driver->monitorname);
1714 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1715 info3.dependentfiles = driver->dependentfiles;
1717 return add_a_printer_driver_3(&info3);
1721 /****************************************************************************
1722 ****************************************************************************/
1723 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
1725 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1729 fstrcpy(info.name, driver);
1730 fstrcpy(info.defaultdatatype, "RAW");
1732 fstrcpy(info.driverpath, "");
1733 fstrcpy(info.datafile, "");
1734 fstrcpy(info.configfile, "");
1735 fstrcpy(info.helpfile, "");
1737 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1740 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1741 fstrcpy(info.dependentfiles[0], "");
1743 *info_ptr = memdup(&info, sizeof(info));
1748 /****************************************************************************
1749 ****************************************************************************/
1750 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
1752 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1753 TDB_DATA kbuf, dbuf;
1754 fstring architecture;
1759 ZERO_STRUCT(driver);
1761 get_short_archi(architecture, arch);
1763 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1765 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1768 kbuf.dsize = strlen(key)+1;
1770 dbuf = tdb_fetch(tdb_drivers, kbuf);
1772 return WERR_UNKNOWN_PRINTER_DRIVER;
1774 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1783 driver.defaultdatatype);
1786 while (len < dbuf.dsize) {
1789 tddfs = (fstring *)Realloc(driver.dependentfiles,
1790 sizeof(fstring)*(i+2));
1791 if (tddfs == NULL) {
1792 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1795 else driver.dependentfiles = tddfs;
1797 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1798 &driver.dependentfiles[i]);
1802 if (driver.dependentfiles != NULL)
1803 fstrcpy(driver.dependentfiles[i], "");
1805 SAFE_FREE(dbuf.dptr);
1807 if (len != dbuf.dsize) {
1808 SAFE_FREE(driver.dependentfiles);
1810 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1813 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1818 /****************************************************************************
1819 Debugging function, dump at level 6 the struct in the logs.
1820 ****************************************************************************/
1822 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1825 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1828 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
1834 if (driver.info_3 == NULL)
1837 info3=driver.info_3;
1839 DEBUGADD(20,("version:[%d]\n", info3->cversion));
1840 DEBUGADD(20,("name:[%s]\n", info3->name));
1841 DEBUGADD(20,("environment:[%s]\n", info3->environment));
1842 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
1843 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
1844 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
1845 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
1846 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
1847 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1849 for (i=0; info3->dependentfiles &&
1850 *info3->dependentfiles[i]; i++) {
1851 DEBUGADD(20,("dependentfile:[%s]\n",
1852 info3->dependentfiles[i]));
1859 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1867 /****************************************************************************
1868 ****************************************************************************/
1869 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1873 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1878 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1879 nt_devmode->devicename,
1880 nt_devmode->formname,
1882 nt_devmode->specversion,
1883 nt_devmode->driverversion,
1885 nt_devmode->driverextra,
1886 nt_devmode->orientation,
1887 nt_devmode->papersize,
1888 nt_devmode->paperlength,
1889 nt_devmode->paperwidth,
1892 nt_devmode->defaultsource,
1893 nt_devmode->printquality,
1896 nt_devmode->yresolution,
1897 nt_devmode->ttoption,
1898 nt_devmode->collate,
1899 nt_devmode->logpixels,
1902 nt_devmode->bitsperpel,
1903 nt_devmode->pelswidth,
1904 nt_devmode->pelsheight,
1905 nt_devmode->displayflags,
1906 nt_devmode->displayfrequency,
1907 nt_devmode->icmmethod,
1908 nt_devmode->icmintent,
1909 nt_devmode->mediatype,
1910 nt_devmode->dithertype,
1911 nt_devmode->reserved1,
1912 nt_devmode->reserved2,
1913 nt_devmode->panningwidth,
1914 nt_devmode->panningheight,
1915 nt_devmode->private);
1918 if (nt_devmode->private) {
1919 len += tdb_pack(buf+len, buflen-len, "B",
1920 nt_devmode->driverextra,
1921 nt_devmode->private);
1924 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1929 /****************************************************************************
1930 Pack all values in all printer keys
1931 ***************************************************************************/
1933 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
1937 REGISTRY_VALUE *val;
1938 REGVAL_CTR *val_ctr;
1945 /* loop over all keys */
1947 for ( i=0; i<data->num_keys; i++ ) {
1948 val_ctr = &data->keys[i].values;
1949 num_values = regval_ctr_numvals( val_ctr );
1951 /* loop over all values */
1953 for ( j=0; j<num_values; j++ ) {
1954 /* pathname should be stored as <key>\<value> */
1956 val = regval_ctr_specific_value( val_ctr, j );
1957 pstrcpy( path, data->keys[i].name );
1958 pstrcat( path, "\\" );
1959 pstrcat( path, regval_name(val) );
1961 len += tdb_pack(buf+len, buflen-len, "pPdB",
1966 regval_data_p(val) );
1973 len += tdb_pack(buf+len, buflen-len, "p", NULL);
1979 /****************************************************************************
1980 Delete a printer - this just deletes the printer info file, any open
1981 handles are not affected.
1982 ****************************************************************************/
1984 uint32 del_a_printer(char *sharename)
1989 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1992 kbuf.dsize=strlen(key)+1;
1994 tdb_delete(tdb_printers, kbuf);
1998 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
1999 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, const char* sharename);
2000 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
2001 /****************************************************************************
2002 ****************************************************************************/
2003 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2009 TDB_DATA kbuf, dbuf;
2012 * in addprinter: no servername and the printer is the name
2013 * in setprinter: servername is \\server
2014 * and printer is \\server\\printer
2016 * Samba manages only local printers.
2017 * we currently don't support things like path=\\other_server\printer
2020 if (info->servername[0]!='\0') {
2021 trim_string(info->printername, info->servername, NULL);
2022 trim_string(info->printername, "\\", NULL);
2023 info->servername[0]='\0';
2027 * JFM: one day I'll forget.
2028 * below that's info->portname because that's the SAMBA sharename
2029 * and I made NT 'thinks' it's the portname
2030 * the info->sharename is the thing you can name when you add a printer
2031 * that's the short-name when you create shared printer for 95/98
2032 * So I've made a limitation in SAMBA: you can only have 1 printer model
2033 * behind a SAMBA share.
2041 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2044 info->default_priority,
2061 info->printprocessor,
2065 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2067 len += pack_values( &info->data, buf+len, buflen-len );
2069 if (buflen != len) {
2072 tb = (char *)Realloc(buf, len);
2074 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2084 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2087 kbuf.dsize = strlen(key)+1;
2091 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2094 if (!W_ERROR_IS_OK(ret))
2095 DEBUG(8, ("error updating printer to tdb on disk\n"));
2099 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2100 info->sharename, info->drivername, info->portname, len));
2106 /****************************************************************************
2107 Malloc and return an NT devicemode.
2108 ****************************************************************************/
2110 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2113 char adevice[MAXDEVICENAME+1];
2114 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2116 if (nt_devmode == NULL) {
2117 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2121 ZERO_STRUCTP(nt_devmode);
2123 safe_strcpy(adevice, default_devicename, sizeof(adevice)-1);
2124 fstrcpy(nt_devmode->devicename, adevice);
2126 fstrcpy(nt_devmode->formname, "Letter");
2128 nt_devmode->specversion = 0x0401;
2129 nt_devmode->driverversion = 0x0400;
2130 nt_devmode->size = 0x00DC;
2131 nt_devmode->driverextra = 0x0000;
2132 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2133 DEFAULTSOURCE | COPIES | SCALE |
2134 PAPERSIZE | ORIENTATION;
2135 nt_devmode->orientation = 1;
2136 nt_devmode->papersize = PAPER_LETTER;
2137 nt_devmode->paperlength = 0;
2138 nt_devmode->paperwidth = 0;
2139 nt_devmode->scale = 0x64;
2140 nt_devmode->copies = 1;
2141 nt_devmode->defaultsource = BIN_FORMSOURCE;
2142 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2143 nt_devmode->color = COLOR_MONOCHROME;
2144 nt_devmode->duplex = DUP_SIMPLEX;
2145 nt_devmode->yresolution = 0;
2146 nt_devmode->ttoption = TT_SUBDEV;
2147 nt_devmode->collate = COLLATE_FALSE;
2148 nt_devmode->icmmethod = 0;
2149 nt_devmode->icmintent = 0;
2150 nt_devmode->mediatype = 0;
2151 nt_devmode->dithertype = 0;
2153 /* non utilisés par un driver d'imprimante */
2154 nt_devmode->logpixels = 0;
2155 nt_devmode->bitsperpel = 0;
2156 nt_devmode->pelswidth = 0;
2157 nt_devmode->pelsheight = 0;
2158 nt_devmode->displayflags = 0;
2159 nt_devmode->displayfrequency = 0;
2160 nt_devmode->reserved1 = 0;
2161 nt_devmode->reserved2 = 0;
2162 nt_devmode->panningwidth = 0;
2163 nt_devmode->panningheight = 0;
2165 nt_devmode->private = NULL;
2169 /****************************************************************************
2170 Deepcopy an NT devicemode.
2171 ****************************************************************************/
2173 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2175 NT_DEVICEMODE *new_nt_devicemode = NULL;
2177 if ( !nt_devicemode )
2180 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2181 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2185 new_nt_devicemode->private = NULL;
2186 if (nt_devicemode->private != NULL) {
2187 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2188 SAFE_FREE(new_nt_devicemode);
2189 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2194 return new_nt_devicemode;
2197 /****************************************************************************
2198 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2199 ****************************************************************************/
2201 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2203 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2205 if(nt_devmode == NULL)
2208 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2210 SAFE_FREE(nt_devmode->private);
2211 SAFE_FREE(*devmode_ptr);
2214 /****************************************************************************
2215 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2216 ****************************************************************************/
2217 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2219 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2220 NT_PRINTER_DATA *data;
2226 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2228 free_nt_devicemode(&info->devmode);
2230 /* clean up all registry keys */
2233 for ( i=0; i<data->num_keys; i++ ) {
2234 SAFE_FREE( data->keys[i].name );
2235 regval_ctr_destroy( &data->keys[i].values );
2237 SAFE_FREE( data->keys );
2239 /* finally the top level structure */
2241 SAFE_FREE( *info_ptr );
2245 /****************************************************************************
2246 ****************************************************************************/
2247 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2251 NT_DEVICEMODE devmode;
2253 ZERO_STRUCT(devmode);
2255 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2257 if (!*nt_devmode) return len;
2259 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2263 &devmode.specversion,
2264 &devmode.driverversion,
2266 &devmode.driverextra,
2267 &devmode.orientation,
2269 &devmode.paperlength,
2270 &devmode.paperwidth,
2273 &devmode.defaultsource,
2274 &devmode.printquality,
2277 &devmode.yresolution,
2283 &devmode.bitsperpel,
2285 &devmode.pelsheight,
2286 &devmode.displayflags,
2287 &devmode.displayfrequency,
2291 &devmode.dithertype,
2294 &devmode.panningwidth,
2295 &devmode.panningheight,
2298 if (devmode.private) {
2299 /* the len in tdb_unpack is an int value and
2300 * devmode.driverextra is only a short
2302 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2303 devmode.driverextra=(uint16)extra_len;
2305 /* check to catch an invalid TDB entry so we don't segfault */
2306 if (devmode.driverextra == 0) {
2307 devmode.private = NULL;
2311 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2313 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2314 if (devmode.private)
2315 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2320 /****************************************************************************
2321 Allocate and initialize a new slot.
2322 ***************************************************************************/
2324 static int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2329 if ( !data || !name )
2332 /* allocate another slot in the NT_PRINTER_KEY array */
2334 d = Realloc( data->keys, sizeof(NT_PRINTER_KEY)*(data->num_keys+1) );
2338 key_index = data->num_keys;
2340 /* initialze new key */
2343 data->keys[key_index].name = strdup( name );
2345 ZERO_STRUCTP( &data->keys[key_index].values );
2347 regval_ctr_init( &data->keys[key_index].values );
2349 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2354 /****************************************************************************
2355 search for a registry key name in the existing printer data
2356 ***************************************************************************/
2358 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2363 if ( !data || !name )
2366 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2368 /* loop over all existing keys */
2370 for ( i=0; i<data->num_keys; i++ ) {
2371 if ( strequal(data->keys[i].name, name) ) {
2372 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2382 /****************************************************************************
2383 ***************************************************************************/
2385 uint32 get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2389 int num_subkeys = 0;
2391 fstring *ptr, *subkeys_ptr = NULL;
2397 for ( i=0; i<data->num_keys; i++ ) {
2398 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2399 /* match sure it is a subkey and not the key itself */
2401 key_len = strlen( key );
2402 if ( strlen(data->keys[i].name) == key_len )
2405 /* get subkey path */
2407 p = data->keys[i].name + key_len;
2410 fstrcpy( subkeyname, p );
2411 if ( (p = strchr( subkeyname, '\\' )) )
2414 /* don't add a key more than once */
2416 for ( j=0; j<num_subkeys; j++ ) {
2417 if ( strequal( subkeys_ptr[j], subkeyname ) )
2421 if ( j != num_subkeys )
2424 /* found a match, so allocate space and copy the name */
2426 if ( !(ptr = Realloc( subkeys_ptr, (num_subkeys+2)*sizeof(fstring))) ) {
2427 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2429 SAFE_FREE( subkeys );
2434 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2440 /* tag of the end */
2443 fstrcpy(subkeys_ptr[num_subkeys], "" );
2445 *subkeys = subkeys_ptr;
2450 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2453 smb_ucs2_t conv_str[1024];
2456 regval_ctr_delvalue(ctr, val_name);
2457 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2458 STR_TERMINATE | STR_NOALIGN);
2459 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2460 (char *) conv_str, str_size);
2463 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2466 regval_ctr_delvalue(ctr, val_name);
2467 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2468 (char *) &dword, sizeof(dword));
2471 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2474 uint8 bin_bool = (bool ? 1 : 0);
2475 regval_ctr_delvalue(ctr, val_name);
2476 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2477 (char *) &bin_bool, sizeof(bin_bool));
2480 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2481 const char *multi_sz)
2483 smb_ucs2_t *conv_strs = NULL;
2486 /* a multi-sz has to have a null string terminator, i.e., the last
2487 string must be followed by two nulls */
2488 str_size = (strlen(multi_sz) + 2) * sizeof(smb_ucs2_t);
2489 conv_strs = calloc(str_size, 1);
2491 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2492 STR_TERMINATE | STR_NOALIGN);
2494 regval_ctr_delvalue(ctr, val_name);
2495 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2496 (char *) conv_strs, str_size);
2497 safe_free(conv_strs);
2501 /****************************************************************************
2502 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2504 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2505 * @return BOOL indicating success or failure
2506 ***************************************************************************/
2508 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2510 REGVAL_CTR *ctr = NULL;
2512 char *allocated_string = NULL;
2513 const char *ascii_str;
2516 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2517 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2518 ctr = &info2->data.keys[i].values;
2520 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2521 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2523 get_myfullname(longname);
2524 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2526 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2527 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2528 SAFE_FREE(allocated_string);
2530 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2531 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2532 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2533 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2534 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2535 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2536 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2537 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2538 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2540 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2541 (info2->attributes &
2542 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2544 switch (info2->attributes & 0x3) {
2546 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2549 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2552 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2555 ascii_str = "unknown";
2557 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2563 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2, GUID guid)
2566 REGVAL_CTR *ctr=NULL;
2568 /* find the DsSpooler key */
2569 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2570 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2571 ctr = &info2->data.keys[i].values;
2573 regval_ctr_delvalue(ctr, "objectGUID");
2574 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2575 (char *) &guid, sizeof(GUID));
2578 static WERROR publish_it(NT_PRINTER_INFO_LEVEL *printer)
2581 TALLOC_CTX *ctx = talloc_init("publish_it");
2582 ADS_MODLIST mods = ads_init_mods(ctx);
2583 char *prt_dn = NULL, *srv_dn, **srv_cn;
2586 const char *attrs[] = {"objectGUID", NULL};
2588 WERROR win_rc = WERR_OK;
2591 /* set the DsSpooler info and attributes */
2592 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2)))
2594 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2595 win_rc = mod_a_printer(*printer, 2);
2596 if (!W_ERROR_IS_OK(win_rc)) {
2597 DEBUG(3, ("err %d saving data\n",
2598 W_ERROR_V(win_rc)));
2602 /* Build the ads mods */
2603 get_local_printer_publishing_data(ctx, &mods,
2604 &printer->info_2->data);
2605 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
2606 printer->info_2->sharename);
2608 /* connect to the ADS server */
2609 ads = ads_init(NULL, NULL, lp_ads_server());
2611 DEBUG(3, ("ads_init() failed\n"));
2612 return WERR_SERVER_UNAVAILABLE;
2614 ads_rc = ads_connect(ads);
2615 if (!ADS_ERR_OK(ads_rc)) {
2616 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2618 return WERR_ACCESS_DENIED;
2621 /* figure out where to publish */
2622 ads_find_machine_acct(ads, &res, global_myname());
2623 srv_dn = ldap_get_dn(ads->ld, res);
2624 ads_msgfree(ads, res);
2625 srv_cn = ldap_explode_dn(srv_dn, 1);
2626 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0],
2627 printer->info_2->sharename, srv_dn);
2628 ads_memfree(ads, srv_dn);
2631 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2632 if (LDAP_ALREADY_EXISTS == ads_rc.err.rc)
2633 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx,&mods);
2635 /* retreive the guid and store it locally */
2636 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2637 ads_memfree(ads, prt_dn);
2638 ads_pull_guid(ads, res, &guid);
2639 ads_msgfree(ads, res);
2640 store_printer_guid(printer->info_2, guid);
2641 win_rc = mod_a_printer(*printer, 2);
2650 WERROR unpublish_it(NT_PRINTER_INFO_LEVEL *printer)
2655 char *prt_dn = NULL;
2658 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2659 win_rc = mod_a_printer(*printer, 2);
2660 if (!W_ERROR_IS_OK(win_rc)) {
2661 DEBUG(3, ("err %d saving data\n",
2662 W_ERROR_V(win_rc)));
2666 ads = ads_init(NULL, NULL, lp_ads_server());
2668 DEBUG(3, ("ads_init() failed\n"));
2669 return WERR_SERVER_UNAVAILABLE;
2671 ads_rc = ads_connect(ads);
2672 if (!ADS_ERR_OK(ads_rc)) {
2673 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2675 return WERR_ACCESS_DENIED;
2678 /* remove the printer from the directory */
2679 ads_rc = ads_find_printer_on_server(ads, &res,
2680 printer->info_2->sharename, global_myname());
2681 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2682 prt_dn = ads_get_dn(ads, res);
2683 ads_msgfree(ads, res);
2684 ads_rc = ads_del_dn(ads, prt_dn);
2685 ads_memfree(ads, prt_dn);
2692 /****************************************************************************
2693 * Publish a printer in the directory
2695 * @param snum describing printer service
2696 * @return WERROR indicating status of publishing
2697 ***************************************************************************/
2699 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2701 NT_PRINTER_INFO_LEVEL *printer = NULL;
2704 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2705 if (!W_ERROR_IS_OK(win_rc))
2709 case SPOOL_DS_PUBLISH:
2710 case SPOOL_DS_UPDATE:
2711 win_rc = publish_it(printer);
2713 case SPOOL_DS_UNPUBLISH:
2714 win_rc = unpublish_it(printer);
2717 win_rc = WERR_NOT_SUPPORTED;
2721 free_a_printer(&printer, 2);
2725 BOOL is_printer_published(Printer_entry *print_hnd, int snum, GUID *guid)
2727 NT_PRINTER_INFO_LEVEL *printer = NULL;
2729 REGISTRY_VALUE *guid_val;
2734 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2735 if (!W_ERROR_IS_OK(win_rc))
2738 if (!(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
2741 if ((i = lookup_printerkey(&printer->info_2->data,
2742 SPOOL_DSSPOOLER_KEY)) < 0)
2745 if (!(ctr = &printer->info_2->data.keys[i].values)) {
2749 if (!(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
2753 if (regval_size(guid_val) == sizeof(GUID))
2754 memcpy(guid, regval_data_p(guid_val), sizeof(GUID));
2760 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2764 BOOL is_printer_published(Printer_entry *print_hnd, int snum, GUID *guid)
2769 /****************************************************************************
2770 ***************************************************************************/
2772 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
2774 NT_PRINTER_DATA *data;
2776 int removed_keys = 0;
2780 empty_slot = data->num_keys;
2783 return WERR_INVALID_PARAM;
2785 /* remove all keys */
2787 if ( !strlen(key) ) {
2788 for ( i=0; i<data->num_keys; i++ ) {
2789 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2790 data->keys[i].name));
2792 SAFE_FREE( data->keys[i].name );
2793 regval_ctr_destroy( &data->keys[i].values );
2796 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2799 SAFE_FREE( data->keys );
2800 ZERO_STRUCTP( data );
2805 /* remove a specific key (and all subkeys) */
2807 for ( i=0; i<data->num_keys; i++ ) {
2808 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
2809 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2810 data->keys[i].name));
2812 SAFE_FREE( data->keys[i].name );
2813 regval_ctr_destroy( &data->keys[i].values );
2815 /* mark the slot as empty */
2817 ZERO_STRUCTP( &data->keys[i] );
2821 /* find the first empty slot */
2823 for ( i=0; i<data->num_keys; i++ ) {
2824 if ( !data->keys[i].name ) {
2831 if ( i == data->num_keys )
2832 /* nothing was removed */
2833 return WERR_INVALID_PARAM;
2835 /* move everything down */
2837 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
2838 if ( data->keys[i].name ) {
2839 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
2840 ZERO_STRUCTP( &data->keys[i] );
2848 data->num_keys -= removed_keys;
2850 /* sanity check to see if anything is left */
2852 if ( !data->num_keys ) {
2853 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
2855 SAFE_FREE( data->keys );
2856 ZERO_STRUCTP( data );
2862 /****************************************************************************
2863 ***************************************************************************/
2865 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
2867 WERROR result = WERR_OK;
2870 /* we must have names on non-zero length */
2872 if ( !key || !*key|| !value || !*value )
2873 return WERR_INVALID_NAME;
2875 /* find the printer key first */
2877 key_index = lookup_printerkey( &p2->data, key );
2878 if ( key_index == -1 )
2881 regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
2883 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2889 /****************************************************************************
2890 ***************************************************************************/
2892 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
2893 uint32 type, uint8 *data, int real_len )
2895 WERROR result = WERR_OK;
2898 /* we must have names on non-zero length */
2900 if ( !key || !*key|| !value || !*value )
2901 return WERR_INVALID_NAME;
2903 /* find the printer key first */
2905 key_index = lookup_printerkey( &p2->data, key );
2906 if ( key_index == -1 )
2907 key_index = add_new_printer_key( &p2->data, key );
2909 if ( key_index == -1 )
2912 regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
2913 type, data, real_len );
2915 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
2916 key, value, type, real_len ));
2921 /****************************************************************************
2922 ***************************************************************************/
2924 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
2928 if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
2931 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
2934 return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
2937 /****************************************************************************
2938 Unpack a list of registry values frem the TDB
2939 ***************************************************************************/
2941 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
2945 pstring string, valuename, keyname;
2949 REGISTRY_VALUE *regval_p;
2952 /* add the "PrinterDriverData" key first for performance reasons */
2954 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
2956 /* loop and unpack the rest of the registry values */
2960 /* check to see if there are any more registry values */
2962 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
2966 /* unpack the next regval */
2968 len += tdb_unpack(buf+len, buflen-len, "fdB",
2975 * break of the keyname from the value name.
2976 * Should only be one '\' in the string returned.
2979 str = strrchr( string, '\\');
2981 /* Put in "PrinterDriverData" is no key specified */
2984 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
2985 pstrcpy( valuename, string );
2989 pstrcpy( keyname, string );
2990 pstrcpy( valuename, str+1 );
2993 /* see if we need a new key */
2995 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
2996 key_index = add_new_printer_key( printer_data, keyname );
2998 if ( key_index == -1 ) {
2999 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3004 /* add the new value */
3006 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, data_p, size );
3008 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3010 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3016 /****************************************************************************
3017 ***************************************************************************/
3019 static void map_to_os2_driver(fstring drivername)
3021 static BOOL initialised=False;
3022 static fstring last_from,last_to;
3023 char *mapfile = lp_os2_driver_map();
3024 char **lines = NULL;
3028 if (!strlen(drivername))
3035 *last_from = *last_to = 0;
3039 if (strequal(drivername,last_from)) {
3040 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3041 fstrcpy(drivername,last_to);
3045 lines = file_lines_load(mapfile, &numlines);
3046 if (numlines == 0) {
3047 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3051 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3053 for( i = 0; i < numlines; i++) {
3054 char *nt_name = lines[i];
3055 char *os2_name = strchr(nt_name,'=');
3062 while (isspace(*nt_name))
3065 if (!*nt_name || strchr("#;",*nt_name))
3069 int l = strlen(nt_name);
3070 while (l && isspace(nt_name[l-1])) {
3076 while (isspace(*os2_name))
3080 int l = strlen(os2_name);
3081 while (l && isspace(os2_name[l-1])) {
3087 if (strequal(nt_name,drivername)) {
3088 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3089 fstrcpy(last_from,drivername);
3090 fstrcpy(last_to,os2_name);
3091 fstrcpy(drivername,os2_name);
3092 file_lines_free(lines);
3097 file_lines_free(lines);
3100 /****************************************************************************
3101 Get a default printer info 2 struct.
3102 ****************************************************************************/
3103 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3106 NT_PRINTER_INFO_LEVEL_2 info;
3110 snum = lp_servicenumber(sharename);
3112 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3113 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
3114 get_called_name(), sharename);
3115 fstrcpy(info.sharename, sharename);
3116 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3118 /* by setting the driver name to an empty string, a local NT admin
3119 can now run the **local** APW to install a local printer driver
3120 for a Samba shared printer in 2.2. Without this, drivers **must** be
3121 installed on the Samba server for NT clients --jerry */
3122 #if 0 /* JERRY --do not uncomment-- */
3123 if (!*info.drivername)
3124 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3128 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3130 pstrcpy(info.comment, "");
3131 fstrcpy(info.printprocessor, "winprint");
3132 fstrcpy(info.datatype, "RAW");
3134 info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3136 info.starttime = 0; /* Minutes since 12:00am GMT */
3137 info.untiltime = 0; /* Minutes since 12:00am GMT */
3139 info.default_priority = 1;
3140 info.setuptime = (uint32)time(NULL);
3143 * I changed this as I think it is better to have a generic
3144 * DEVMODE than to crash Win2k explorer.exe --jerry
3145 * See the HP Deskjet 990c Win2k drivers for an example.
3147 * However the default devmode appears to cause problems
3148 * with the HP CLJ 8500 PCL driver. Hence the addition of
3149 * the "default devmode" parameter --jerry 22/01/2002
3152 if (lp_default_devmode(snum)) {
3153 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3157 info.devmode = NULL;
3160 /* This will get the current RPC talloc context, but we should be
3161 passing this as a parameter... fixme... JRA ! */
3163 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3166 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3168 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3176 free_nt_devicemode(&info.devmode);
3177 return WERR_ACCESS_DENIED;
3180 /****************************************************************************
3181 ****************************************************************************/
3182 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3185 NT_PRINTER_INFO_LEVEL_2 info;
3187 TDB_DATA kbuf, dbuf;
3188 fstring printername;
3192 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
3195 kbuf.dsize = strlen(key)+1;
3197 dbuf = tdb_fetch(tdb_printers, kbuf);
3199 return get_a_printer_2_default(info_ptr, sharename);
3201 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3204 &info.default_priority,
3221 info.printprocessor,
3225 /* Samba has to have shared raw drivers. */
3226 info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3228 /* Restore the stripped strings. */
3229 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3230 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
3232 fstrcpy(info.printername, printername);
3234 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3237 * Some client drivers freak out if there is a NULL devmode
3238 * (probably the driver is not checking before accessing
3239 * the devmode pointer) --jerry
3241 * See comments in get_a_printer_2_default()
3244 if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode) {
3245 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3247 info.devmode = construct_nt_devicemode(printername);
3250 len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3252 /* This will get the current RPC talloc context, but we should be
3253 passing this as a parameter... fixme... JRA ! */
3255 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3257 /* Fix for OS/2 drivers. */
3259 if (get_remote_arch() == RA_OS2)
3260 map_to_os2_driver(info.drivername);
3262 SAFE_FREE(dbuf.dptr);
3263 *info_ptr=memdup(&info, sizeof(info));
3265 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3266 sharename, info.printername, info.drivername));
3271 /****************************************************************************
3272 Debugging function, dump at level 6 the struct in the logs.
3273 ****************************************************************************/
3274 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3277 NT_PRINTER_INFO_LEVEL_2 *info2;
3279 DEBUG(106,("Dumping printer at level [%d]\n", level));
3284 if (printer.info_2 == NULL)
3288 info2=printer.info_2;
3290 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3291 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3292 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3293 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3294 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3295 DEBUGADD(106,("status:[%d]\n", info2->status));
3296 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3297 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3298 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3299 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3300 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3302 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3303 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3304 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3305 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3306 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3307 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3308 DEBUGADD(106,("location:[%s]\n", info2->location));
3309 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3310 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3311 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3312 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3318 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3326 /****************************************************************************
3327 Update the changeid time.
3328 This is SO NASTY as some drivers need this to change, others need it
3329 static. This value will change every second, and I must hope that this
3330 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3332 ****************************************************************************/
3334 static uint32 rev_changeid(void)
3338 get_process_uptime(&tv);
3341 /* Return changeid as msec since spooler restart */
3342 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3345 * This setting seems to work well but is too untested
3346 * to replace the above calculation. Left in for experiementation
3347 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3349 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3354 * The function below are the high level ones.
3355 * only those ones must be called from the spoolss code.
3359 /****************************************************************************
3360 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3361 ****************************************************************************/
3363 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3367 dump_a_printer(printer, level);
3370 * invalidate cache for all open handles to this printer.
3371 * cache for a given handle will be updated on the next
3375 invalidate_printer_hnd_cache( printer.info_2->sharename );
3381 * Update the changestamp. Emperical tests show that the
3382 * ChangeID is always updated,but c_setprinter is
3383 * global spooler variable (not per printer).
3386 /* ChangeID **must** be increasing over the lifetime
3387 of client's spoolss service in order for the
3388 client's cache to show updates */
3390 printer.info_2->changeid = rev_changeid();
3393 * Because one day someone will ask:
3394 * NT->NT An admin connection to a remote
3395 * printer show changes imeediately in
3396 * the properities dialog
3398 * A non-admin connection will only show the
3399 * changes after viewing the properites page
3400 * 2 times. Seems to be related to a
3401 * race condition in the client between the spooler
3402 * updating the local cache and the Explorer.exe GUI
3403 * actually displaying the properties.
3405 * This is fixed in Win2k. admin/non-admin
3406 * connections both display changes immediately.
3411 result=update_a_printer_2(printer.info_2);
3416 result=WERR_UNKNOWN_LEVEL;
3423 /****************************************************************************
3424 Initialize printer devmode & data with previously saved driver init values.
3425 ****************************************************************************/
3427 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3431 TDB_DATA kbuf, dbuf;
3432 NT_PRINTER_INFO_LEVEL_2 info;
3438 * Delete any printer data 'values' already set. When called for driver
3439 * replace, there will generally be some, but during an add printer, there
3440 * should not be any (if there are delete them).
3443 delete_all_printer_data( info_ptr, "" );
3445 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3448 kbuf.dsize = strlen(key)+1;
3450 dbuf = tdb_fetch(tdb_drivers, kbuf);
3453 * When changing to a driver that has no init info in the tdb, remove
3454 * the previous drivers init info and leave the new on blank.
3456 free_nt_devicemode(&info_ptr->devmode);
3461 * Get the saved DEVMODE..
3464 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3467 * The saved DEVMODE contains the devicename from the printer used during
3468 * the initialization save. Change it to reflect the new printer.
3471 if ( info.devmode ) {
3472 ZERO_STRUCT(info.devmode->devicename);
3473 fstrcpy(info.devmode->devicename, info_ptr->printername);
3477 * NT/2k does not change out the entire DeviceMode of a printer
3478 * when changing the driver. Only the driverextra, private, &
3479 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3481 * Later examination revealed that Windows NT/2k does reset the
3482 * the printer's device mode, bit **only** when you change a
3483 * property of the device mode such as the page orientation.
3488 /* Bind the saved DEVMODE to the new the printer */
3490 free_nt_devicemode(&info_ptr->devmode);
3491 info_ptr->devmode = info.devmode;
3493 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3494 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3496 /* Add the printer data 'values' to the new printer */
3498 len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3501 SAFE_FREE(dbuf.dptr);
3506 /****************************************************************************
3507 Initialize printer devmode & data with previously saved driver init values.
3508 When a printer is created using AddPrinter, the drivername bound to the
3509 printer is used to lookup previously saved driver initialization info, which
3510 is bound to the new printer.
3511 ****************************************************************************/
3513 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3515 BOOL result = False;
3519 result = set_driver_init_2(printer->info_2);
3523 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3531 /****************************************************************************
3532 Delete driver init data stored for a specified driver
3533 ****************************************************************************/
3535 BOOL del_driver_init(char *drivername)
3540 if (!drivername || !*drivername) {
3541 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3545 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3548 kbuf.dsize = strlen(key)+1;
3550 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3552 return (tdb_delete(tdb_drivers, kbuf) == 0);
3555 /****************************************************************************
3556 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3557 in the tdb. Note: this is different from the driver entry and the printer
3558 entry. There should be a single driver init entry for each driver regardless
3559 of whether it was installed from NT or 2K. Technically, they should be
3560 different, but they work out to the same struct.
3561 ****************************************************************************/
3563 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3567 int buflen, len, ret;
3568 TDB_DATA kbuf, dbuf;
3575 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3577 len += pack_values( &info->data, buf+len, buflen-len );
3579 if (buflen != len) {
3582 tb = (char *)Realloc(buf, len);
3584 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3594 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3597 kbuf.dsize = strlen(key)+1;
3601 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3605 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3609 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3610 info->sharename, info->drivername));
3615 /****************************************************************************
3616 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3617 ****************************************************************************/
3619 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3623 dump_a_printer(printer, level);
3627 result = update_driver_init_2(printer.info_2);
3637 /****************************************************************************
3638 Convert the printer data value, a REG_BINARY array, into an initialization
3639 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3640 got to keep the endians happy :).
3641 ****************************************************************************/
3643 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
3645 BOOL result = False;
3649 ZERO_STRUCT(devmode);
3651 prs_init(&ps, 0, ctx, UNMARSHALL);
3652 ps.data_p = (char *)data;
3653 ps.buffer_size = data_len;
3655 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3656 result = convert_devicemode("", &devmode, &nt_devmode);
3658 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3663 /****************************************************************************
3664 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3666 1. Use the driver's config DLL to this UNC printername and:
3667 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3668 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3669 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3671 The last step triggers saving the "driver initialization" information for
3672 this printer into the tdb. Later, new printers that use this driver will
3673 have this initialization information bound to them. This simulates the
3674 driver initialization, as if it had run on the Samba server (as it would
3677 The Win32 client side code requirement sucks! But until we can run arbitrary
3678 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3680 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3681 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3682 about it and you will realize why. JRR 010720
3683 ****************************************************************************/
3685 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
3687 WERROR status = WERR_OK;
3688 TALLOC_CTX *ctx = NULL;
3689 NT_DEVICEMODE *nt_devmode = NULL;
3690 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3693 * When the DEVMODE is already set on the printer, don't try to unpack it.
3695 DEBUG(8,("save_driver_init_2: Enter...\n"));
3697 if ( !printer->info_2->devmode && data_len ) {
3699 * Set devmode on printer info, so entire printer initialization can be
3703 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
3706 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3707 status = WERR_NOMEM;
3711 ZERO_STRUCTP(nt_devmode);
3714 * The DEVMODE is held in the 'data' component of the param in raw binary.
3715 * Convert it to to a devmode structure
3717 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
3718 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3719 status = WERR_INVALID_PARAM;
3723 printer->info_2->devmode = nt_devmode;
3727 * Pack up and add (or update) the DEVMODE and any current printer data to
3728 * a 'driver init' element in the tdb
3732 if ( update_driver_init(*printer, 2) != 0 ) {
3733 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3734 status = WERR_NOMEM;
3739 * If driver initialization info was successfully saved, set the current
3740 * printer to match it. This allows initialization of the current printer
3741 * as well as the driver.
3743 status = mod_a_printer(*printer, 2);
3744 if (!W_ERROR_IS_OK(status)) {
3745 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3746 printer->info_2->printername));
3750 talloc_destroy(ctx);
3751 free_nt_devicemode( &nt_devmode );
3753 printer->info_2->devmode = tmp_devmode;
3758 /****************************************************************************
3759 Update the driver init info (DEVMODE and specifics) for a printer
3760 ****************************************************************************/
3762 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
3764 WERROR status = WERR_OK;
3768 status = save_driver_init_2( printer, data, data_len );
3771 status = WERR_UNKNOWN_LEVEL;
3778 /****************************************************************************
3779 Deep copy a NT_PRINTER_DATA
3780 ****************************************************************************/
3782 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
3784 int i, j, num_vals, new_key_index;
3785 REGVAL_CTR *src_key, *dst_key;
3788 return NT_STATUS_NO_MEMORY;
3790 for ( i=0; i<src->num_keys; i++ ) {
3792 /* create a new instance of the printerkey in the destination
3793 printer_data object */
3795 new_key_index = add_new_printer_key( dst, src->keys[i].name );
3796 dst_key = &dst->keys[new_key_index].values;
3798 src_key = &src->keys[i].values;
3799 num_vals = regval_ctr_numvals( src_key );
3801 /* dup the printer entire printer key */
3803 for ( j=0; j<num_vals; j++ ) {
3804 regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
3808 return NT_STATUS_OK;
3811 /****************************************************************************
3812 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
3814 ****************************************************************************/
3816 static NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
3818 NT_PRINTER_INFO_LEVEL_2 *copy;
3823 if ( !(copy = (NT_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2))) )
3826 memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
3828 /* malloc()'d members copied here */
3830 copy->devmode = dup_nt_devicemode( printer->devmode );
3832 ZERO_STRUCT( copy->data );
3833 copy_printer_data( ©->data, &printer->data );
3835 /* this is talloc()'d; very ugly that we have a structure that
3836 is half malloc()'d and half talloc()'d but that is the way
3837 that the PRINTER_INFO stuff is written right now. --jerry */
3839 copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
3844 /****************************************************************************
3845 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3846 ****************************************************************************/
3848 #define ENABLE_PRINT_HND_CACHE 1
3850 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
3851 const char *sharename)
3854 NT_PRINTER_INFO_LEVEL *printer = NULL;
3858 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3862 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3863 DEBUG(0,("get_a_printer: malloc fail.\n"));
3866 ZERO_STRUCTP(printer);
3869 * check for cache first. A Printer handle cannot changed
3870 * to another printer object so we only check that the printer
3871 * is actually for a printer and that the printer_info pointer
3874 #ifdef ENABLE_PRINT_HND_CACHE /* JERRY */
3876 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)
3877 && print_hnd->printer_info )
3879 if ( !(printer->info_2 = dup_printer_2(print_hnd->ctx, print_hnd->printer_info->info_2)) ) {
3880 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
3886 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
3888 *pp_printer = printer;
3895 /* no cache; look it up on disk */
3897 result=get_a_printer_2(&printer->info_2, sharename);
3898 if (W_ERROR_IS_OK(result)) {
3899 dump_a_printer(*printer, level);
3901 #if ENABLE_PRINT_HND_CACHE /* JERRY */
3902 /* save a copy in cache */
3903 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
3904 if ( !print_hnd->printer_info )
3905 print_hnd->printer_info = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL));
3907 if ( print_hnd->printer_info ) {
3908 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
3910 /* don't fail the lookup just because the cache update failed */
3911 if ( !print_hnd->printer_info->info_2 )
3912 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
3917 *pp_printer = printer;
3925 result=WERR_UNKNOWN_LEVEL;
3929 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
3934 /****************************************************************************
3935 Deletes a NT_PRINTER_INFO_LEVEL struct.
3936 ****************************************************************************/
3938 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3941 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3943 DEBUG(104,("freeing a printer at level [%d]\n", level));
3945 if (printer == NULL)
3950 if (printer->info_2 != NULL) {
3951 free_nt_printer_info_level_2(&printer->info_2);
3962 SAFE_FREE(*pp_printer);
3966 /****************************************************************************
3967 ****************************************************************************/
3968 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3971 DEBUG(104,("adding a printer at level [%d]\n", level));
3972 dump_a_printer_driver(driver, level);
3976 result=add_a_printer_driver_3(driver.info_3);
3980 result=add_a_printer_driver_6(driver.info_6);
3990 /****************************************************************************
3991 ****************************************************************************/
3993 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3994 fstring drivername, const char *architecture, uint32 version)
4000 /* Sometime we just want any version of the driver */
4002 if ( version == DRIVER_ANY_VERSION ) {
4003 /* look for Win2k first and then for NT4 */
4004 result = get_a_printer_driver_3(&driver->info_3, drivername,
4007 if ( !W_ERROR_IS_OK(result) ) {
4008 result = get_a_printer_driver_3( &driver->info_3,
4009 drivername, architecture, 2 );
4012 result = get_a_printer_driver_3(&driver->info_3, drivername,
4013 architecture, version);
4022 if (W_ERROR_IS_OK(result))
4023 dump_a_printer_driver(*driver, level);
4028 /****************************************************************************
4029 ****************************************************************************/
4030 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4037 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4038 if (driver.info_3 != NULL)
4040 info3=driver.info_3;
4041 SAFE_FREE(info3->dependentfiles);
4042 ZERO_STRUCTP(info3);
4052 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4053 if (driver.info_6 != NULL) {
4054 info6=driver.info_6;
4055 SAFE_FREE(info6->dependentfiles);
4056 SAFE_FREE(info6->previousnames);
4057 ZERO_STRUCTP(info6);
4073 /****************************************************************************
4074 Determine whether or not a particular driver is currently assigned
4076 ****************************************************************************/
4078 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4081 int n_services = lp_numservices();
4082 NT_PRINTER_INFO_LEVEL *printer = NULL;
4087 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4089 /* loop through the printers.tdb and check for the drivername */
4091 for (snum=0; snum<n_services; snum++) {
4092 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4095 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4098 if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
4099 free_a_printer( &printer, 2 );
4103 free_a_printer( &printer, 2 );
4106 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4108 /* report that the driver is not in use by default */
4114 /**********************************************************************
4115 Check to see if a ogiven file is in use by *info
4116 *********************************************************************/
4118 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4125 if ( strequal(file, info->driverpath) )
4128 if ( strequal(file, info->datafile) )
4131 if ( strequal(file, info->configfile) )
4134 if ( strequal(file, info->helpfile) )
4137 /* see of there are any dependent files to examine */
4139 if ( !info->dependentfiles )
4142 while ( *info->dependentfiles[i] ) {
4143 if ( strequal(file, info->dependentfiles[i]) )
4152 /**********************************************************************
4153 Utility function to remove the dependent file pointed to by the
4154 input parameter from the list
4155 *********************************************************************/
4157 static void trim_dependent_file( fstring files[], int idx )
4160 /* bump everything down a slot */
4162 while( *files[idx+1] ) {
4163 fstrcpy( files[idx], files[idx+1] );
4172 /**********************************************************************
4173 Check if any of the files used by src are also used by drv
4174 *********************************************************************/
4176 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4177 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4179 BOOL in_use = False;
4185 /* check each file. Remove it from the src structure if it overlaps */
4187 if ( drv_file_in_use(src->driverpath, drv) ) {
4189 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4190 fstrcpy( src->driverpath, "" );
4193 if ( drv_file_in_use(src->datafile, drv) ) {
4195 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4196 fstrcpy( src->datafile, "" );
4199 if ( drv_file_in_use(src->configfile, drv) ) {
4201 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4202 fstrcpy( src->configfile, "" );
4205 if ( drv_file_in_use(src->helpfile, drv) ) {
4207 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4208 fstrcpy( src->helpfile, "" );
4211 /* are there any dependentfiles to examine? */
4213 if ( !src->dependentfiles )
4216 while ( *src->dependentfiles[i] ) {
4217 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4219 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4220 trim_dependent_file( src->dependentfiles, i );
4228 /****************************************************************************
4229 Determine whether or not a particular driver files are currently being
4230 used by any other driver.
4232 Return value is True if any files were in use by other drivers
4233 and False otherwise.
4235 Upon return, *info has been modified to only contain the driver files
4236 which are not in use
4237 ****************************************************************************/
4239 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4244 fstring *list = NULL;
4245 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4250 version = info->cversion;
4252 /* loop over all driver versions */
4254 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4256 /* get the list of drivers */
4259 ndrivers = get_ntdrivers(&list, info->environment, version);
4261 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4262 ndrivers, info->environment, version));
4264 /* check each driver for overlap in files */
4266 for (i=0; i<ndrivers; i++) {
4267 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4269 ZERO_STRUCT(driver);
4271 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4276 /* check if d2 uses any files from d1 */
4277 /* only if this is a different driver than the one being deleted */
4279 if ( !strequal(info->name, driver.info_3->name) ) {
4280 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4281 free_a_printer_driver(driver, 3);
4287 free_a_printer_driver(driver, 3);
4292 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4294 driver.info_3 = info;
4296 if ( DEBUGLEVEL >= 20 )
4297 dump_a_printer_driver( driver, 3 );
4302 /****************************************************************************
4303 Actually delete the driver files. Make sure that
4304 printer_driver_files_in_use() return False before calling
4306 ****************************************************************************/
4308 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4312 connection_struct *conn;
4320 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4323 * Connect to the print$ share under the same account as the
4324 * user connected to the rpc pipe. Note we must be root to
4328 null_pw = data_blob( NULL, 0 );
4329 fstrcpy(res_type, "A:");
4331 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4335 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4339 /* Save who we are - we are temporarily becoming the connection user. */
4341 if ( !become_user(conn, conn->vuid) ) {
4342 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4346 /* now delete the files; must strip the '\print$' string from
4349 if ( *info_3->driverpath ) {
4350 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4351 DEBUG(10,("deleting driverfile [%s]\n", s));
4352 unlink_internals(conn, 0, s);
4356 if ( *info_3->configfile ) {
4357 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4358 DEBUG(10,("deleting configfile [%s]\n", s));
4359 unlink_internals(conn, 0, s);
4363 if ( *info_3->datafile ) {
4364 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4365 DEBUG(10,("deleting datafile [%s]\n", s));
4366 unlink_internals(conn, 0, s);
4370 if ( *info_3->helpfile ) {
4371 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4372 DEBUG(10,("deleting helpfile [%s]\n", s));
4373 unlink_internals(conn, 0, s);
4377 /* check if we are done removing files */
4379 if ( info_3->dependentfiles ) {
4380 while ( *info_3->dependentfiles[i] ) {
4383 /* bypass the "\print$" portion of the path */
4385 if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4386 DEBUG(10,("deleting dependent file [%s]\n", file));
4387 unlink_internals(conn, 0, file );
4399 /****************************************************************************
4400 Remove a printer driver from the TDB. This assumes that the the driver was
4401 previously looked up.
4402 ***************************************************************************/
4404 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4405 uint32 version, BOOL delete_files )
4409 TDB_DATA kbuf, dbuf;
4410 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4412 /* delete the tdb data first */
4414 get_short_archi(arch, info_3->environment);
4415 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4416 arch, version, info_3->name);
4418 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4419 key, delete_files ? "TRUE" : "FALSE" ));
4421 ctr.info_3 = info_3;
4422 dump_a_printer_driver( ctr, 3 );
4425 kbuf.dsize=strlen(key)+1;
4427 /* check if the driver actually exists for this environment */
4429 dbuf = tdb_fetch( tdb_drivers, kbuf );
4431 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4432 return WERR_UNKNOWN_PRINTER_DRIVER;
4435 SAFE_FREE( dbuf.dptr );
4437 /* ok... the driver exists so the delete should return success */
4439 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4440 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4441 return WERR_ACCESS_DENIED;
4445 * now delete any associated files if delete_files == True
4446 * even if this part failes, we return succes because the
4447 * driver doesn not exist any more
4451 delete_driver_files( info_3, user );
4454 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4459 /****************************************************************************
4460 Store a security desc for a printer.
4461 ****************************************************************************/
4463 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4465 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4466 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4468 TALLOC_CTX *mem_ctx = NULL;
4472 mem_ctx = talloc_init("nt_printing_setsec");
4473 if (mem_ctx == NULL)
4476 /* The old owner and group sids of the security descriptor are not
4477 present when new ACEs are added or removed by changing printer
4478 permissions through NT. If they are NULL in the new security
4479 descriptor then copy them over from the old one. */
4481 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4482 DOM_SID *owner_sid, *group_sid;
4483 SEC_ACL *dacl, *sacl;
4484 SEC_DESC *psd = NULL;
4487 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4489 /* Pick out correct owner and group sids */
4491 owner_sid = secdesc_ctr->sec->owner_sid ?
4492 secdesc_ctr->sec->owner_sid :
4493 old_secdesc_ctr->sec->owner_sid;
4495 group_sid = secdesc_ctr->sec->grp_sid ?
4496 secdesc_ctr->sec->grp_sid :
4497 old_secdesc_ctr->sec->grp_sid;
4499 dacl = secdesc_ctr->sec->dacl ?
4500 secdesc_ctr->sec->dacl :
4501 old_secdesc_ctr->sec->dacl;
4503 sacl = secdesc_ctr->sec->sacl ?
4504 secdesc_ctr->sec->sacl :
4505 old_secdesc_ctr->sec->sacl;
4507 /* Make a deep copy of the security descriptor */
4509 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
4510 owner_sid, group_sid,
4515 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4518 if (!new_secdesc_ctr) {
4519 new_secdesc_ctr = secdesc_ctr;
4522 /* Store the security descriptor in a tdb */
4524 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4525 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4527 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4529 status = WERR_BADFUNC;
4533 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4535 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4538 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4539 status = WERR_BADFUNC;
4542 /* Free malloc'ed memory */
4548 talloc_destroy(mem_ctx);
4552 /****************************************************************************
4553 Construct a default security descriptor buffer for a printer.
4554 ****************************************************************************/
4556 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4560 SEC_ACL *psa = NULL;
4561 SEC_DESC_BUF *sdb = NULL;
4562 SEC_DESC *psd = NULL;
4566 /* Create an ACE where Everyone is allowed to print */
4568 init_sec_access(&sa, PRINTER_ACE_PRINT);
4569 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4570 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4572 /* Make the security descriptor owned by the Administrators group
4573 on the PDC of the domain. */
4575 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4576 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4579 /* Backup plan - make printer owned by admins.
4580 This should emulate a lanman printer as security
4581 settings can't be changed. */
4583 sid_copy(&owner_sid, get_global_sam_sid());
4584 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4587 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4588 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4589 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4590 SEC_ACE_FLAG_INHERIT_ONLY);
4592 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4593 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4594 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4596 /* The ACL revision number in rpc_secdesc.h differs from the one
4597 created by NT when setting ACE entries in printer
4598 descriptors. NT4 complains about the property being edited by a
4601 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4602 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
4604 NULL, psa, &sd_size);
4608 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4612 sdb = make_sec_desc_buf(ctx, sd_size, psd);
4614 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4615 (unsigned int)sd_size));
4620 /****************************************************************************
4621 Get a security desc for a printer.
4622 ****************************************************************************/
4624 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4630 if (strlen(printername) > 2 && (temp = strchr(printername + 2, '\\'))) {
4631 printername = temp + 1;
4634 /* Fetch security descriptor from tdb */
4636 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4638 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4639 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4641 DEBUG(4,("using default secdesc for %s\n", printername));
4643 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4647 /* Save default security descriptor for later */
4649 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4650 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4652 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4653 tdb_prs_store(tdb_printers, key, &ps);
4660 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4661 this security descriptor has been created when winbindd was
4662 down. Take ownership of security descriptor. */
4664 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4667 /* Change sd owner to workgroup administrator */
4669 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4670 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4671 SEC_DESC *psd = NULL;
4676 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4678 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
4680 (*secdesc_ctr)->sec->grp_sid,
4681 (*secdesc_ctr)->sec->sacl,
4682 (*secdesc_ctr)->sec->dacl,
4685 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4687 /* Swap with other one */
4689 *secdesc_ctr = new_secdesc_ctr;
4693 nt_printing_setsec(printername, *secdesc_ctr);
4697 if (DEBUGLEVEL >= 10) {
4698 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4701 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4702 printername, the_acl->num_aces));
4704 for (i = 0; i < the_acl->num_aces; i++) {
4707 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4709 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4710 the_acl->ace[i].type, the_acl->ace[i].flags,
4711 the_acl->ace[i].info.mask));
4721 1: level not implemented
4722 2: file doesn't exist
4723 3: can't allocate memory
4724 4: can't free memory
4725 5: non existant struct
4729 A printer and a printer driver are 2 different things.
4730 NT manages them separatelly, Samba does the same.
4731 Why ? Simply because it's easier and it makes sense !
4733 Now explanation: You have 3 printers behind your samba server,
4734 2 of them are the same make and model (laser A and B). But laser B
4735 has an 3000 sheet feeder and laser A doesn't such an option.
4736 Your third printer is an old dot-matrix model for the accounting :-).
4738 If the /usr/local/samba/lib directory (default dir), you will have
4739 5 files to describe all of this.
4741 3 files for the printers (1 by printer):
4744 NTprinter_accounting
4745 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4746 NTdriver_printer model X
4747 NTdriver_printer model Y
4749 jfm: I should use this comment for the text file to explain
4750 same thing for the forms BTW.
4751 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4755 /* Convert generic access rights to printer object specific access rights.
4756 It turns out that NT4 security descriptors use generic access rights and
4757 NT5 the object specific ones. */
4759 void map_printer_permissions(SEC_DESC *sd)
4763 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4764 se_map_generic(&sd->dacl->ace[i].info.mask,
4765 &printer_generic_mapping);
4769 /****************************************************************************
4770 Check a user has permissions to perform the given operation. We use the
4771 permission constants defined in include/rpc_spoolss.h to check the various
4772 actions we perform when checking printer access.
4774 PRINTER_ACCESS_ADMINISTER:
4775 print_queue_pause, print_queue_resume, update_printer_sec,
4776 update_printer, spoolss_addprinterex_level_2,
4777 _spoolss_setprinterdata
4782 JOB_ACCESS_ADMINISTER:
4783 print_job_delete, print_job_pause, print_job_resume,
4786 ****************************************************************************/
4787 BOOL print_access_check(struct current_user *user, int snum, int access_type)
4789 SEC_DESC_BUF *secdesc = NULL;
4790 uint32 access_granted;
4794 TALLOC_CTX *mem_ctx = NULL;
4795 extern struct current_user current_user;
4797 /* If user is NULL then use the current_user structure */
4800 user = ¤t_user;
4802 /* Always allow root or printer admins to do anything */
4804 if (user->uid == 0 ||
4805 user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups)) {
4809 /* Get printer name */
4811 pname = PRINTERNAME(snum);
4813 if (!pname || !*pname) {
4818 /* Get printer security descriptor */
4820 if(!(mem_ctx = talloc_init("print_access_check"))) {
4825 nt_printing_getsec(mem_ctx, pname, &secdesc);
4827 if (access_type == JOB_ACCESS_ADMINISTER) {
4828 SEC_DESC_BUF *parent_secdesc = secdesc;
4830 /* Create a child security descriptor to check permissions
4831 against. This is because print jobs are child objects
4832 objects of a printer. */
4834 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4836 /* Now this is the bit that really confuses me. The access
4837 type needs to be changed from JOB_ACCESS_ADMINISTER to
4838 PRINTER_ACCESS_ADMINISTER for this to work. Something
4839 to do with the child (job) object becoming like a
4842 access_type = PRINTER_ACCESS_ADMINISTER;
4847 map_printer_permissions(secdesc->sec);
4849 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4850 &access_granted, &status);
4852 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4854 talloc_destroy(mem_ctx);
4862 /****************************************************************************
4863 Check the time parameters allow a print operation.
4864 *****************************************************************************/
4866 BOOL print_time_access_check(int snum)
4868 NT_PRINTER_INFO_LEVEL *printer = NULL;
4870 time_t now = time(NULL);
4874 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
4877 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
4881 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4883 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
4886 free_a_printer(&printer, 2);