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}
202 const char *long_archi;
203 const char *short_archi;
207 #define SPL_ARCH_WIN40 "WIN40"
208 #define SPL_ARCH_W32X86 "W32X86"
209 #define SPL_ARCH_W32MIPS "W32MIPS"
210 #define SPL_ARCH_W32ALPHA "W32ALPHA"
211 #define SPL_ARCH_W32PPC "W32PPC"
213 static const struct table_node archi_table[]= {
215 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
216 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
217 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
218 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
219 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
223 static BOOL upgrade_to_version_3(void)
225 TDB_DATA kbuf, newkey, dbuf;
227 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
229 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
230 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
232 dbuf = tdb_fetch(tdb_drivers, kbuf);
234 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
235 DEBUG(0,("upgrade_to_version_3:moving form\n"));
236 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
237 SAFE_FREE(dbuf.dptr);
238 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
241 if (tdb_delete(tdb_drivers, kbuf) != 0) {
242 SAFE_FREE(dbuf.dptr);
243 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
248 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
249 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
250 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
251 SAFE_FREE(dbuf.dptr);
252 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
255 if (tdb_delete(tdb_drivers, kbuf) != 0) {
256 SAFE_FREE(dbuf.dptr);
257 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
262 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
263 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
264 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
265 SAFE_FREE(dbuf.dptr);
266 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
269 if (tdb_delete(tdb_drivers, kbuf) != 0) {
270 SAFE_FREE(dbuf.dptr);
271 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
276 SAFE_FREE(dbuf.dptr);
282 /****************************************************************************
283 Open the NT printing tdbs. Done once before fork().
284 ****************************************************************************/
286 BOOL nt_printing_init(void)
288 static pid_t local_pid;
289 const char *vstring = "INFO/version";
291 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
295 tdb_close(tdb_drivers);
296 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
298 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
299 lock_path("ntdrivers.tdb"), strerror(errno) ));
304 tdb_close(tdb_printers);
305 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
307 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
308 lock_path("ntprinters.tdb"), strerror(errno) ));
313 tdb_close(tdb_forms);
314 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
316 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
317 lock_path("ntforms.tdb"), strerror(errno) ));
321 local_pid = sys_getpid();
323 /* handle a Samba upgrade */
324 tdb_lock_bystring(tdb_drivers, vstring, 0);
328 /* Cope with byte-reversed older versions of the db. */
329 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
330 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
331 /* Written on a bigendian machine with old fetch_int code. Save as le. */
332 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
333 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
334 vers_id = NTDRIVERS_DATABASE_VERSION;
337 if (vers_id != NTDRIVERS_DATABASE_VERSION) {
339 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
340 if (!upgrade_to_version_3())
343 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
345 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
348 tdb_unlock_bystring(tdb_drivers, vstring);
350 update_c_setprinter(True);
353 * register callback to handle updating printers as new
354 * drivers are installed
357 message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
360 * register callback to handle updating printer data
361 * when a driver is initialized
364 message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
370 /*******************************************************************
371 tdb traversal function for counting printers.
372 ********************************************************************/
374 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
375 TDB_DATA data, void *context)
377 int *printer_count = (int*)context;
379 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
381 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
387 /*******************************************************************
388 Update the spooler global c_setprinter. This variable is initialized
389 when the parent smbd starts with the number of existing printers. It
390 is monotonically increased by the current number of printers *after*
391 each add or delete printer RPC. Only Microsoft knows why... JRR020119
392 ********************************************************************/
394 uint32 update_c_setprinter(BOOL initialize)
397 int32 printer_count = 0;
399 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
401 /* Traverse the tdb, counting the printers */
402 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
404 /* If initializing, set c_setprinter to current printers count
405 * otherwise, bump it by the current printer count
408 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
410 c_setprinter = printer_count;
412 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
413 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
415 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
417 return (uint32)c_setprinter;
420 /*******************************************************************
421 Get the spooler global c_setprinter, accounting for initialization.
422 ********************************************************************/
424 uint32 get_c_setprinter(void)
426 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
428 if (c_setprinter == (int32)-1)
429 c_setprinter = update_c_setprinter(True);
431 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
433 return (uint32)c_setprinter;
436 /****************************************************************************
437 Get builtin form struct list.
438 ****************************************************************************/
440 int get_builtin_ntforms(nt_forms_struct **list)
442 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
443 return sizeof(default_forms) / sizeof(default_forms[0]);
446 /****************************************************************************
447 get a builtin form struct
448 ****************************************************************************/
450 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
454 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
455 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
456 count = sizeof(default_forms) / sizeof(default_forms[0]);
457 for (i=0;i<count;i++) {
458 if (strequal(form_name,default_forms[i].name)) {
459 DEBUGADD(6,("Found builtin form %s \n", form_name));
460 memcpy(form,&default_forms[i],sizeof(*form));
468 /****************************************************************************
469 get a form struct list
470 ****************************************************************************/
471 int get_ntforms(nt_forms_struct **list)
473 TDB_DATA kbuf, newkey, dbuf;
475 nt_forms_struct form;
480 for (kbuf = tdb_firstkey(tdb_forms);
482 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
484 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
487 dbuf = tdb_fetch(tdb_forms, kbuf);
491 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
492 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
493 &i, &form.flag, &form.width, &form.length, &form.left,
494 &form.top, &form.right, &form.bottom);
495 SAFE_FREE(dbuf.dptr);
496 if (ret != dbuf.dsize)
499 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
501 DEBUG(0,("get_ntforms: Realloc fail.\n"));
513 /****************************************************************************
514 write a form struct list
515 ****************************************************************************/
516 int write_ntforms(nt_forms_struct **list, int number)
523 for (i=0;i<number;i++) {
524 /* save index, so list is rebuilt in correct order */
525 len = tdb_pack(buf, sizeof(buf), "dddddddd",
526 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
527 (*list)[i].left, (*list)[i].top, (*list)[i].right,
529 if (len > sizeof(buf)) break;
530 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
531 kbuf.dsize = strlen(key)+1;
535 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
541 /****************************************************************************
542 add a form struct at the end of the list
543 ****************************************************************************/
544 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
552 * NT tries to add forms even when
553 * they are already in the base
554 * only update the values if already present
559 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
560 for (n=0; n<*count; n++) {
561 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
562 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
569 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
570 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
574 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
578 (*list)[n].flag=form->flags;
579 (*list)[n].width=form->size_x;
580 (*list)[n].length=form->size_y;
581 (*list)[n].left=form->left;
582 (*list)[n].top=form->top;
583 (*list)[n].right=form->right;
584 (*list)[n].bottom=form->bottom;
589 /****************************************************************************
590 Delete a named form struct.
591 ****************************************************************************/
593 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
602 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
604 for (n=0; n<*count; n++) {
605 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
606 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
612 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
613 *ret = WERR_INVALID_PARAM;
617 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
618 kbuf.dsize = strlen(key)+1;
620 if (tdb_delete(tdb_forms, kbuf) != 0) {
628 /****************************************************************************
629 Update a form struct.
630 ****************************************************************************/
632 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
636 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
638 DEBUG(106, ("[%s]\n", form_name));
639 for (n=0; n<count; n++) {
640 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
641 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
645 if (n==count) return;
647 (*list)[n].flag=form->flags;
648 (*list)[n].width=form->size_x;
649 (*list)[n].length=form->size_y;
650 (*list)[n].left=form->left;
651 (*list)[n].top=form->top;
652 (*list)[n].right=form->right;
653 (*list)[n].bottom=form->bottom;
656 /****************************************************************************
657 Get the nt drivers list.
658 Traverse the database and look-up the matching names.
659 ****************************************************************************/
660 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
663 const char *short_archi;
666 TDB_DATA kbuf, newkey;
668 short_archi = get_short_archi(architecture);
669 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
671 for (kbuf = tdb_firstkey(tdb_drivers);
673 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
675 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
678 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
679 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
684 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
691 /****************************************************************************
692 function to do the mapping between the long architecture name and
694 ****************************************************************************/
695 const char *get_short_archi(const char *long_archi)
699 DEBUG(107,("Getting architecture dependant directory\n"));
702 } while ( (archi_table[i].long_archi!=NULL ) &&
703 StrCaseCmp(long_archi, archi_table[i].long_archi) );
705 if (archi_table[i].long_archi==NULL) {
706 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
710 /* this might be client code - but shouldn't this be an fstrcpy etc? */
713 DEBUGADD(108,("index: [%d]\n", i));
714 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
715 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
717 return archi_table[i].short_archi;
720 /****************************************************************************
721 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
722 There are two case to be covered here: PE (Portable Executable) and NE (New
723 Executable) files. Both files support the same INFO structure, but PE files
724 store the signature in unicode, and NE files store it as !unicode.
725 returns -1 on error, 1 on version info found, and 0 on no version info found.
726 ****************************************************************************/
728 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
734 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
735 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
736 fname, PE_HEADER_SIZE));
740 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
741 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
742 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
744 goto no_version_info;
747 /* Is this really a DOS header? */
748 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
749 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
750 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
751 goto no_version_info;
754 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
755 if (SMB_VFS_LSEEK(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
756 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
758 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
759 goto no_version_info;
762 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
763 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
765 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
766 goto no_version_info;
769 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
770 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
772 int section_table_bytes;
774 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
775 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
776 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
777 /* At this point, we assume the file is in error. It still could be somthing
778 * else besides a PE file, but it unlikely at this point.
783 /* get the section table */
784 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
785 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
787 if ((buf=malloc(section_table_bytes)) == NULL) {
788 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
789 fname, section_table_bytes));
793 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
794 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
799 /* Iterate the section table looking for the resource section ".rsrc" */
800 for (i = 0; i < num_sections; i++) {
801 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
803 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
804 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
805 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
808 if ((buf=malloc(section_bytes)) == NULL) {
809 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
810 fname, section_bytes));
814 /* Seek to the start of the .rsrc section info */
815 if (SMB_VFS_LSEEK(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
816 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
821 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
822 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
827 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
828 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
829 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
830 /* Align to next long address */
831 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
833 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
834 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
835 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
837 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
838 fname, *major, *minor,
839 (*major>>16)&0xffff, *major&0xffff,
840 (*minor>>16)&0xffff, *minor&0xffff));
849 /* Version info not found, fall back to origin date/time */
850 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
854 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
855 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
856 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
857 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
858 /* At this point, we assume the file is in error. It still could be somthing
859 * else besides a NE file, but it unlikely at this point. */
863 /* Allocate a bit more space to speed up things */
865 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
866 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
867 fname, PE_HEADER_SIZE));
871 /* This is a HACK! I got tired of trying to sort through the messy
872 * 'NE' file format. If anyone wants to clean this up please have at
873 * it, but this works. 'NE' files will eventually fade away. JRR */
874 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
875 /* Cover case that should not occur in a well formed 'NE' .dll file */
876 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
878 for(i=0; i<byte_count; i++) {
879 /* Fast skip past data that can't possibly match */
880 if (buf[i] != 'V') continue;
882 /* Potential match data crosses buf boundry, move it to beginning
883 * of buf, and fill the buf with as much as it will hold. */
884 if (i>byte_count-VS_VERSION_INFO_SIZE) {
887 memcpy(buf, &buf[i], byte_count-i);
888 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
889 (byte_count-i))) < 0) {
891 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
896 byte_count = bc + (byte_count - i);
897 if (byte_count<VS_VERSION_INFO_SIZE) break;
902 /* Check that the full signature string and the magic number that
903 * follows exist (not a perfect solution, but the chances that this
904 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
905 * twice, as it is simpler to read the code. */
906 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
907 /* Compute skip alignment to next long address */
908 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
909 sizeof(VS_SIGNATURE)) & 3;
910 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
912 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
913 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
914 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
915 fname, *major, *minor,
916 (*major>>16)&0xffff, *major&0xffff,
917 (*minor>>16)&0xffff, *minor&0xffff));
924 /* Version info not found, fall back to origin date/time */
925 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
930 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
931 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
932 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
943 /****************************************************************************
944 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
945 share one or more files. During the MS installation process files are checked
946 to insure that only a newer version of a shared file is installed over an
947 older version. There are several possibilities for this comparison. If there
948 is no previous version, the new one is newer (obviously). If either file is
949 missing the version info structure, compare the creation date (on Unix use
950 the modification date). Otherwise chose the numerically larger version number.
951 ****************************************************************************/
953 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
955 BOOL use_version = True;
960 time_t new_create_time;
964 time_t old_create_time;
968 files_struct *fsp = NULL;
970 SMB_STRUCT_STAT stat_buf;
974 ZERO_STRUCT(stat_buf);
975 new_create_time = (time_t)0;
976 old_create_time = (time_t)0;
978 /* Get file version info (if available) for previous file (if it exists) */
979 pstrcpy(filepath, old_file);
981 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
983 fsp = open_file_shared(conn, filepath, &stat_buf,
984 SET_OPEN_MODE(DOS_OPEN_RDONLY),
985 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
986 0, 0, &access_mode, &action);
988 /* Old file not found, so by definition new file is in fact newer */
989 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
994 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
995 if (ret == -1) goto error_exit;
998 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1000 use_version = False;
1001 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1002 old_create_time = st.st_mtime;
1003 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1006 close_file(fsp, True);
1008 /* Get file version info (if available) for new file */
1009 pstrcpy(filepath, new_file);
1010 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1012 fsp = open_file_shared(conn, filepath, &stat_buf,
1013 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1014 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1015 0, 0, &access_mode, &action);
1017 /* New file not found, this shouldn't occur if the caller did its job */
1018 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1023 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1024 if (ret == -1) goto error_exit;
1027 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1029 use_version = False;
1030 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1031 new_create_time = st.st_mtime;
1032 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1035 close_file(fsp, True);
1037 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1038 /* Compare versions and choose the larger version number */
1039 if (new_major > old_major ||
1040 (new_major == old_major && new_minor > old_minor)) {
1042 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1046 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1051 /* Compare modification time/dates and choose the newest time/date */
1052 if (new_create_time > old_create_time) {
1053 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1057 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1064 close_file(fsp, True);
1068 /****************************************************************************
1069 Determine the correct cVersion associated with an architecture and driver
1070 ****************************************************************************/
1071 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1072 struct current_user *user, WERROR *perr)
1081 files_struct *fsp = NULL;
1084 connection_struct *conn;
1088 *perr = WERR_INVALID_PARAM;
1090 /* If architecture is Windows 95/98/ME, the version is always 0. */
1091 if (strcmp(architecture, "WIN40") == 0) {
1092 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1098 * Connect to the print$ share under the same account as the user connected
1099 * to the rpc pipe. Note we must still be root to do this.
1102 /* Null password is ok - we are already an authenticated user... */
1103 null_pw = data_blob(NULL, 0);
1104 fstrcpy(res_type, "A:");
1106 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1110 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1111 *perr = ntstatus_to_werror(nt_status);
1115 /* We are temporarily becoming the connection user. */
1116 if (!become_user(conn, user->vuid)) {
1117 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1118 *perr = WERR_ACCESS_DENIED;
1122 /* Open the driver file (Portable Executable format) and determine the
1123 * deriver the cversion. */
1124 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1126 unix_convert(driverpath,conn,NULL,&bad_path,&st);
1128 fsp = open_file_shared(conn, driverpath, &st,
1129 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1130 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1131 0, 0, &access_mode, &action);
1133 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1134 driverpath, errno));
1135 *perr = WERR_ACCESS_DENIED;
1141 int ret = get_file_version(fsp, driverpath, &major, &minor);
1142 if (ret == -1) goto error_exit;
1145 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1150 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1151 * for more details. Version in this case is not just the version of the
1152 * file, but the version in the sense of kernal mode (2) vs. user mode
1153 * (3) drivers. Other bits of the version fields are the version info.
1156 cversion = major & 0x0000ffff;
1158 case 2: /* WinNT drivers */
1159 case 3: /* Win2K drivers */
1163 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1164 driverpath, cversion));
1168 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1169 driverpath, major, minor));
1172 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1173 driverpath, cversion));
1175 close_file(fsp, True);
1176 close_cnum(conn, user->vuid);
1185 close_file(fsp, True);
1187 close_cnum(conn, user->vuid);
1192 /****************************************************************************
1193 ****************************************************************************/
1194 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1195 struct current_user *user)
1197 const char *architecture;
1203 /* clean up the driver name.
1204 * we can get .\driver.dll
1205 * or worse c:\windows\system\driver.dll !
1207 /* using an intermediate string to not have overlaping memcpy()'s */
1208 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1209 fstrcpy(new_name, p+1);
1210 fstrcpy(driver->driverpath, new_name);
1213 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1214 fstrcpy(new_name, p+1);
1215 fstrcpy(driver->datafile, new_name);
1218 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1219 fstrcpy(new_name, p+1);
1220 fstrcpy(driver->configfile, new_name);
1223 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1224 fstrcpy(new_name, p+1);
1225 fstrcpy(driver->helpfile, new_name);
1228 if (driver->dependentfiles) {
1229 for (i=0; *driver->dependentfiles[i]; i++) {
1230 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1231 fstrcpy(new_name, p+1);
1232 fstrcpy(driver->dependentfiles[i], new_name);
1237 architecture = get_short_archi(driver->environment);
1239 /* jfm:7/16/2000 the client always sends the cversion=0.
1240 * The server should check which version the driver is by reading
1241 * the PE header of driver->driverpath.
1243 * For Windows 95/98 the version is 0 (so the value sent is correct)
1244 * For Windows NT (the architecture doesn't matter)
1245 * NT 3.1: cversion=0
1246 * NT 3.5/3.51: cversion=1
1250 if ((driver->cversion = get_correct_cversion( architecture,
1251 driver->driverpath, user, &err)) == -1)
1257 /****************************************************************************
1258 ****************************************************************************/
1259 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1261 const char *architecture;
1267 /* clean up the driver name.
1268 * we can get .\driver.dll
1269 * or worse c:\windows\system\driver.dll !
1271 /* using an intermediate string to not have overlaping memcpy()'s */
1272 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1273 fstrcpy(new_name, p+1);
1274 fstrcpy(driver->driverpath, new_name);
1277 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1278 fstrcpy(new_name, p+1);
1279 fstrcpy(driver->datafile, new_name);
1282 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1283 fstrcpy(new_name, p+1);
1284 fstrcpy(driver->configfile, new_name);
1287 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1288 fstrcpy(new_name, p+1);
1289 fstrcpy(driver->helpfile, new_name);
1292 if (driver->dependentfiles) {
1293 for (i=0; *driver->dependentfiles[i]; i++) {
1294 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1295 fstrcpy(new_name, p+1);
1296 fstrcpy(driver->dependentfiles[i], new_name);
1301 architecture = get_short_archi(driver->environment);
1303 /* jfm:7/16/2000 the client always sends the cversion=0.
1304 * The server should check which version the driver is by reading
1305 * the PE header of driver->driverpath.
1307 * For Windows 95/98 the version is 0 (so the value sent is correct)
1308 * For Windows NT (the architecture doesn't matter)
1309 * NT 3.1: cversion=0
1310 * NT 3.5/3.51: cversion=1
1314 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1320 /****************************************************************************
1321 ****************************************************************************/
1322 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1323 uint32 level, struct current_user *user)
1328 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1329 driver=driver_abstract.info_3;
1330 return clean_up_driver_struct_level_3(driver, user);
1334 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1335 driver=driver_abstract.info_6;
1336 return clean_up_driver_struct_level_6(driver, user);
1339 return WERR_INVALID_PARAM;
1343 /****************************************************************************
1344 This function sucks and should be replaced. JRA.
1345 ****************************************************************************/
1347 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1349 dst->cversion = src->version;
1351 fstrcpy( dst->name, src->name);
1352 fstrcpy( dst->environment, src->environment);
1353 fstrcpy( dst->driverpath, src->driverpath);
1354 fstrcpy( dst->datafile, src->datafile);
1355 fstrcpy( dst->configfile, src->configfile);
1356 fstrcpy( dst->helpfile, src->helpfile);
1357 fstrcpy( dst->monitorname, src->monitorname);
1358 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1359 dst->dependentfiles = src->dependentfiles;
1362 #if 0 /* Debugging function */
1364 static char* ffmt(unsigned char *c){
1366 static char ffmt_str[17];
1368 for (i=0; i<16; i++) {
1369 if ((c[i] < ' ') || (c[i] > '~'))
1380 /****************************************************************************
1381 ****************************************************************************/
1382 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1383 struct current_user *user, WERROR *perr)
1385 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1386 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1387 const char *architecture;
1392 connection_struct *conn;
1400 memset(inbuf, '\0', sizeof(inbuf));
1401 memset(outbuf, '\0', sizeof(outbuf));
1405 driver=driver_abstract.info_3;
1406 else if (level==6) {
1407 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1408 driver = &converted_driver;
1410 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1414 architecture = get_short_archi(driver->environment);
1417 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1418 * Note we must be root to do this.
1421 null_pw = data_blob(NULL, 0);
1422 fstrcpy(res_type, "A:");
1424 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1428 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1429 *perr = ntstatus_to_werror(nt_status);
1434 * Save who we are - we are temporarily becoming the connection user.
1437 if (!become_user(conn, conn->vuid)) {
1438 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1443 * make the directories version and version\driver_name
1444 * under the architecture directory.
1446 DEBUG(5,("Creating first directory\n"));
1447 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1448 mkdir_internal(conn, new_dir);
1450 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1451 * listed for this driver which has already been moved, skip it (note:
1452 * drivers may list the same file name several times. Then check if the
1453 * file already exists in archi\cversion\, if so, check that the version
1454 * info (or time stamps if version info is unavailable) is newer (or the
1455 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1456 * Otherwise, delete the file.
1458 * If a file is not moved to archi\cversion\ because of an error, all the
1459 * rest of the 'unmoved' driver files are removed from archi\. If one or
1460 * more of the driver's files was already moved to archi\cversion\, it
1461 * potentially leaves the driver in a partially updated state. Version
1462 * trauma will most likely occur if an client attempts to use any printer
1463 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1464 * done is appropriate... later JRR
1467 DEBUG(5,("Moving files now !\n"));
1469 if (driver->driverpath && strlen(driver->driverpath)) {
1470 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1471 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1472 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1474 status = rename_internals(conn, new_name, old_name, True);
1475 if (!NT_STATUS_IS_OK(status)) {
1476 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1477 new_name, old_name));
1478 *perr = ntstatus_to_werror(status);
1479 unlink_internals(conn, 0, new_name);
1484 unlink_internals(conn, 0, new_name);
1487 if (driver->datafile && strlen(driver->datafile)) {
1488 if (!strequal(driver->datafile, driver->driverpath)) {
1489 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1490 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1491 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1493 status = rename_internals(conn, new_name, old_name, True);
1494 if (!NT_STATUS_IS_OK(status)) {
1495 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1496 new_name, old_name));
1497 *perr = ntstatus_to_werror(status);
1498 unlink_internals(conn, 0, new_name);
1503 unlink_internals(conn, 0, new_name);
1507 if (driver->configfile && strlen(driver->configfile)) {
1508 if (!strequal(driver->configfile, driver->driverpath) &&
1509 !strequal(driver->configfile, driver->datafile)) {
1510 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1511 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1512 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1514 status = rename_internals(conn, new_name, old_name, True);
1515 if (!NT_STATUS_IS_OK(status)) {
1516 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1517 new_name, old_name));
1518 *perr = ntstatus_to_werror(status);
1519 unlink_internals(conn, 0, new_name);
1524 unlink_internals(conn, 0, new_name);
1528 if (driver->helpfile && strlen(driver->helpfile)) {
1529 if (!strequal(driver->helpfile, driver->driverpath) &&
1530 !strequal(driver->helpfile, driver->datafile) &&
1531 !strequal(driver->helpfile, driver->configfile)) {
1532 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1533 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1534 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1536 status = rename_internals(conn, new_name, old_name, True);
1537 if (!NT_STATUS_IS_OK(status)) {
1538 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1539 new_name, old_name));
1540 *perr = ntstatus_to_werror(status);
1541 unlink_internals(conn, 0, new_name);
1546 unlink_internals(conn, 0, new_name);
1550 if (driver->dependentfiles) {
1551 for (i=0; *driver->dependentfiles[i]; i++) {
1552 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1553 !strequal(driver->dependentfiles[i], driver->datafile) &&
1554 !strequal(driver->dependentfiles[i], driver->configfile) &&
1555 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1557 for (j=0; j < i; j++) {
1558 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1563 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1564 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1565 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1567 status = rename_internals(conn, new_name, old_name, True);
1568 if (!NT_STATUS_IS_OK(status)) {
1569 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1570 new_name, old_name));
1571 *perr = ntstatus_to_werror(status);
1572 unlink_internals(conn, 0, new_name);
1577 unlink_internals(conn, 0, new_name);
1583 close_cnum(conn, user->vuid);
1586 return ver == -1 ? False : True;
1589 /****************************************************************************
1590 ****************************************************************************/
1591 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1594 const char *architecture;
1600 TDB_DATA kbuf, dbuf;
1602 architecture = get_short_archi(driver->environment);
1604 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1605 * \\server is added in the rpc server layer.
1606 * It does make sense to NOT store the server's name in the printer TDB.
1609 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1611 /* .inf files do not always list a file for each of the four standard files.
1612 * Don't prepend a path to a null filename, or client claims:
1613 * "The server on which the printer resides does not have a suitable
1614 * <printer driver name> printer driver installed. Click OK if you
1615 * wish to install the driver on your local machine."
1617 if (strlen(driver->driverpath)) {
1618 fstrcpy(temp_name, driver->driverpath);
1619 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1622 if (strlen(driver->datafile)) {
1623 fstrcpy(temp_name, driver->datafile);
1624 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1627 if (strlen(driver->configfile)) {
1628 fstrcpy(temp_name, driver->configfile);
1629 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1632 if (strlen(driver->helpfile)) {
1633 fstrcpy(temp_name, driver->helpfile);
1634 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1637 if (driver->dependentfiles) {
1638 for (i=0; *driver->dependentfiles[i]; i++) {
1639 fstrcpy(temp_name, driver->dependentfiles[i]);
1640 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1644 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1646 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1653 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1656 driver->environment,
1661 driver->monitorname,
1662 driver->defaultdatatype);
1664 if (driver->dependentfiles) {
1665 for (i=0; *driver->dependentfiles[i]; i++) {
1666 len += tdb_pack(buf+len, buflen-len, "f",
1667 driver->dependentfiles[i]);
1671 if (len != buflen) {
1674 tb = (char *)Realloc(buf, len);
1676 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1687 kbuf.dsize = strlen(key)+1;
1691 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1695 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1701 /****************************************************************************
1702 ****************************************************************************/
1703 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1705 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1708 info3.cversion = driver->version;
1709 fstrcpy(info3.name,driver->name);
1710 fstrcpy(info3.environment,driver->environment);
1711 fstrcpy(info3.driverpath,driver->driverpath);
1712 fstrcpy(info3.datafile,driver->datafile);
1713 fstrcpy(info3.configfile,driver->configfile);
1714 fstrcpy(info3.helpfile,driver->helpfile);
1715 fstrcpy(info3.monitorname,driver->monitorname);
1716 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1717 info3.dependentfiles = driver->dependentfiles;
1719 return add_a_printer_driver_3(&info3);
1723 /****************************************************************************
1724 ****************************************************************************/
1725 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
1727 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1731 fstrcpy(info.name, driver);
1732 fstrcpy(info.defaultdatatype, "RAW");
1734 fstrcpy(info.driverpath, "");
1735 fstrcpy(info.datafile, "");
1736 fstrcpy(info.configfile, "");
1737 fstrcpy(info.helpfile, "");
1739 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1742 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1743 fstrcpy(info.dependentfiles[0], "");
1745 *info_ptr = memdup(&info, sizeof(info));
1750 /****************************************************************************
1751 ****************************************************************************/
1752 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
1754 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1755 TDB_DATA kbuf, dbuf;
1756 const char *architecture;
1761 ZERO_STRUCT(driver);
1763 architecture = get_short_archi(arch);
1765 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1767 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
1770 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1772 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1775 kbuf.dsize = strlen(key)+1;
1777 dbuf = tdb_fetch(tdb_drivers, kbuf);
1779 return WERR_UNKNOWN_PRINTER_DRIVER;
1781 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1790 driver.defaultdatatype);
1793 while (len < dbuf.dsize) {
1796 tddfs = (fstring *)Realloc(driver.dependentfiles,
1797 sizeof(fstring)*(i+2));
1798 if (tddfs == NULL) {
1799 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1802 else driver.dependentfiles = tddfs;
1804 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1805 &driver.dependentfiles[i]);
1809 if (driver.dependentfiles != NULL)
1810 fstrcpy(driver.dependentfiles[i], "");
1812 SAFE_FREE(dbuf.dptr);
1814 if (len != dbuf.dsize) {
1815 SAFE_FREE(driver.dependentfiles);
1817 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1820 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1825 /****************************************************************************
1826 Debugging function, dump at level 6 the struct in the logs.
1827 ****************************************************************************/
1829 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1832 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1835 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
1841 if (driver.info_3 == NULL)
1844 info3=driver.info_3;
1846 DEBUGADD(20,("version:[%d]\n", info3->cversion));
1847 DEBUGADD(20,("name:[%s]\n", info3->name));
1848 DEBUGADD(20,("environment:[%s]\n", info3->environment));
1849 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
1850 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
1851 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
1852 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
1853 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
1854 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1856 for (i=0; info3->dependentfiles &&
1857 *info3->dependentfiles[i]; i++) {
1858 DEBUGADD(20,("dependentfile:[%s]\n",
1859 info3->dependentfiles[i]));
1866 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1874 /****************************************************************************
1875 ****************************************************************************/
1876 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1880 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1885 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1886 nt_devmode->devicename,
1887 nt_devmode->formname,
1889 nt_devmode->specversion,
1890 nt_devmode->driverversion,
1892 nt_devmode->driverextra,
1893 nt_devmode->orientation,
1894 nt_devmode->papersize,
1895 nt_devmode->paperlength,
1896 nt_devmode->paperwidth,
1899 nt_devmode->defaultsource,
1900 nt_devmode->printquality,
1903 nt_devmode->yresolution,
1904 nt_devmode->ttoption,
1905 nt_devmode->collate,
1906 nt_devmode->logpixels,
1909 nt_devmode->bitsperpel,
1910 nt_devmode->pelswidth,
1911 nt_devmode->pelsheight,
1912 nt_devmode->displayflags,
1913 nt_devmode->displayfrequency,
1914 nt_devmode->icmmethod,
1915 nt_devmode->icmintent,
1916 nt_devmode->mediatype,
1917 nt_devmode->dithertype,
1918 nt_devmode->reserved1,
1919 nt_devmode->reserved2,
1920 nt_devmode->panningwidth,
1921 nt_devmode->panningheight,
1922 nt_devmode->private);
1925 if (nt_devmode->private) {
1926 len += tdb_pack(buf+len, buflen-len, "B",
1927 nt_devmode->driverextra,
1928 nt_devmode->private);
1931 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1936 /****************************************************************************
1937 Pack all values in all printer keys
1938 ***************************************************************************/
1940 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
1944 REGISTRY_VALUE *val;
1945 REGVAL_CTR *val_ctr;
1952 /* loop over all keys */
1954 for ( i=0; i<data->num_keys; i++ ) {
1955 val_ctr = &data->keys[i].values;
1956 num_values = regval_ctr_numvals( val_ctr );
1958 /* loop over all values */
1960 for ( j=0; j<num_values; j++ ) {
1961 /* pathname should be stored as <key>\<value> */
1963 val = regval_ctr_specific_value( val_ctr, j );
1964 pstrcpy( path, data->keys[i].name );
1965 pstrcat( path, "\\" );
1966 pstrcat( path, regval_name(val) );
1968 len += tdb_pack(buf+len, buflen-len, "pPdB",
1973 regval_data_p(val) );
1980 len += tdb_pack(buf+len, buflen-len, "p", NULL);
1986 /****************************************************************************
1987 Delete a printer - this just deletes the printer info file, any open
1988 handles are not affected.
1989 ****************************************************************************/
1991 uint32 del_a_printer(char *sharename)
1996 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1999 kbuf.dsize=strlen(key)+1;
2001 tdb_delete(tdb_printers, kbuf);
2005 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
2006 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, const char* sharename);
2007 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
2008 /****************************************************************************
2009 ****************************************************************************/
2010 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2016 TDB_DATA kbuf, dbuf;
2019 * in addprinter: no servername and the printer is the name
2020 * in setprinter: servername is \\server
2021 * and printer is \\server\\printer
2023 * Samba manages only local printers.
2024 * we currently don't support things like path=\\other_server\printer
2027 if (info->servername[0]!='\0') {
2028 trim_string(info->printername, info->servername, NULL);
2029 trim_char(info->printername, '\\', '\0');
2030 info->servername[0]='\0';
2034 * JFM: one day I'll forget.
2035 * below that's info->portname because that's the SAMBA sharename
2036 * and I made NT 'thinks' it's the portname
2037 * the info->sharename is the thing you can name when you add a printer
2038 * that's the short-name when you create shared printer for 95/98
2039 * So I've made a limitation in SAMBA: you can only have 1 printer model
2040 * behind a SAMBA share.
2048 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2051 info->default_priority,
2068 info->printprocessor,
2072 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2074 len += pack_values( &info->data, buf+len, buflen-len );
2076 if (buflen != len) {
2079 tb = (char *)Realloc(buf, len);
2081 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2091 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2094 kbuf.dsize = strlen(key)+1;
2098 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2101 if (!W_ERROR_IS_OK(ret))
2102 DEBUG(8, ("error updating printer to tdb on disk\n"));
2106 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2107 info->sharename, info->drivername, info->portname, len));
2113 /****************************************************************************
2114 Malloc and return an NT devicemode.
2115 ****************************************************************************/
2117 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2120 char adevice[MAXDEVICENAME];
2121 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2123 if (nt_devmode == NULL) {
2124 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2128 ZERO_STRUCTP(nt_devmode);
2130 safe_strcpy(adevice, default_devicename, sizeof(adevice)-1);
2131 fstrcpy(nt_devmode->devicename, adevice);
2133 fstrcpy(nt_devmode->formname, "Letter");
2135 nt_devmode->specversion = 0x0401;
2136 nt_devmode->driverversion = 0x0400;
2137 nt_devmode->size = 0x00DC;
2138 nt_devmode->driverextra = 0x0000;
2139 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2140 DEFAULTSOURCE | COPIES | SCALE |
2141 PAPERSIZE | ORIENTATION;
2142 nt_devmode->orientation = 1;
2143 nt_devmode->papersize = PAPER_LETTER;
2144 nt_devmode->paperlength = 0;
2145 nt_devmode->paperwidth = 0;
2146 nt_devmode->scale = 0x64;
2147 nt_devmode->copies = 1;
2148 nt_devmode->defaultsource = BIN_FORMSOURCE;
2149 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2150 nt_devmode->color = COLOR_MONOCHROME;
2151 nt_devmode->duplex = DUP_SIMPLEX;
2152 nt_devmode->yresolution = 0;
2153 nt_devmode->ttoption = TT_SUBDEV;
2154 nt_devmode->collate = COLLATE_FALSE;
2155 nt_devmode->icmmethod = 0;
2156 nt_devmode->icmintent = 0;
2157 nt_devmode->mediatype = 0;
2158 nt_devmode->dithertype = 0;
2160 /* non utilisés par un driver d'imprimante */
2161 nt_devmode->logpixels = 0;
2162 nt_devmode->bitsperpel = 0;
2163 nt_devmode->pelswidth = 0;
2164 nt_devmode->pelsheight = 0;
2165 nt_devmode->displayflags = 0;
2166 nt_devmode->displayfrequency = 0;
2167 nt_devmode->reserved1 = 0;
2168 nt_devmode->reserved2 = 0;
2169 nt_devmode->panningwidth = 0;
2170 nt_devmode->panningheight = 0;
2172 nt_devmode->private = NULL;
2176 /****************************************************************************
2177 Deepcopy an NT devicemode.
2178 ****************************************************************************/
2180 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2182 NT_DEVICEMODE *new_nt_devicemode = NULL;
2184 if ( !nt_devicemode )
2187 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2188 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2192 new_nt_devicemode->private = NULL;
2193 if (nt_devicemode->private != NULL) {
2194 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2195 SAFE_FREE(new_nt_devicemode);
2196 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2201 return new_nt_devicemode;
2204 /****************************************************************************
2205 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2206 ****************************************************************************/
2208 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2210 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2212 if(nt_devmode == NULL)
2215 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2217 SAFE_FREE(nt_devmode->private);
2218 SAFE_FREE(*devmode_ptr);
2221 /****************************************************************************
2222 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2223 ****************************************************************************/
2224 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2226 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2227 NT_PRINTER_DATA *data;
2233 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2235 free_nt_devicemode(&info->devmode);
2237 /* clean up all registry keys */
2240 for ( i=0; i<data->num_keys; i++ ) {
2241 SAFE_FREE( data->keys[i].name );
2242 regval_ctr_destroy( &data->keys[i].values );
2244 SAFE_FREE( data->keys );
2246 /* finally the top level structure */
2248 SAFE_FREE( *info_ptr );
2252 /****************************************************************************
2253 ****************************************************************************/
2254 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2258 NT_DEVICEMODE devmode;
2260 ZERO_STRUCT(devmode);
2262 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2264 if (!*nt_devmode) return len;
2266 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2270 &devmode.specversion,
2271 &devmode.driverversion,
2273 &devmode.driverextra,
2274 &devmode.orientation,
2276 &devmode.paperlength,
2277 &devmode.paperwidth,
2280 &devmode.defaultsource,
2281 &devmode.printquality,
2284 &devmode.yresolution,
2290 &devmode.bitsperpel,
2292 &devmode.pelsheight,
2293 &devmode.displayflags,
2294 &devmode.displayfrequency,
2298 &devmode.dithertype,
2301 &devmode.panningwidth,
2302 &devmode.panningheight,
2305 if (devmode.private) {
2306 /* the len in tdb_unpack is an int value and
2307 * devmode.driverextra is only a short
2309 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2310 devmode.driverextra=(uint16)extra_len;
2312 /* check to catch an invalid TDB entry so we don't segfault */
2313 if (devmode.driverextra == 0) {
2314 devmode.private = NULL;
2318 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2320 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2321 if (devmode.private)
2322 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2327 /****************************************************************************
2328 Allocate and initialize a new slot.
2329 ***************************************************************************/
2331 static int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2336 if ( !data || !name )
2339 /* allocate another slot in the NT_PRINTER_KEY array */
2341 d = Realloc( data->keys, sizeof(NT_PRINTER_KEY)*(data->num_keys+1) );
2345 key_index = data->num_keys;
2347 /* initialze new key */
2350 data->keys[key_index].name = strdup( name );
2352 ZERO_STRUCTP( &data->keys[key_index].values );
2354 regval_ctr_init( &data->keys[key_index].values );
2356 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2361 /****************************************************************************
2362 search for a registry key name in the existing printer data
2363 ***************************************************************************/
2365 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2370 if ( !data || !name )
2373 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2375 /* loop over all existing keys */
2377 for ( i=0; i<data->num_keys; i++ ) {
2378 if ( strequal(data->keys[i].name, name) ) {
2379 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2389 /****************************************************************************
2390 ***************************************************************************/
2392 uint32 get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2396 int num_subkeys = 0;
2398 fstring *ptr, *subkeys_ptr = NULL;
2404 for ( i=0; i<data->num_keys; i++ ) {
2405 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2406 /* match sure it is a subkey and not the key itself */
2408 key_len = strlen( key );
2409 if ( strlen(data->keys[i].name) == key_len )
2412 /* get subkey path */
2414 p = data->keys[i].name + key_len;
2417 fstrcpy( subkeyname, p );
2418 if ( (p = strchr( subkeyname, '\\' )) )
2421 /* don't add a key more than once */
2423 for ( j=0; j<num_subkeys; j++ ) {
2424 if ( strequal( subkeys_ptr[j], subkeyname ) )
2428 if ( j != num_subkeys )
2431 /* found a match, so allocate space and copy the name */
2433 if ( !(ptr = Realloc( subkeys_ptr, (num_subkeys+2)*sizeof(fstring))) ) {
2434 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2436 SAFE_FREE( subkeys );
2441 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2447 /* tag of the end */
2450 fstrcpy(subkeys_ptr[num_subkeys], "" );
2452 *subkeys = subkeys_ptr;
2458 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2461 smb_ucs2_t conv_str[1024];
2464 regval_ctr_delvalue(ctr, val_name);
2465 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2466 STR_TERMINATE | STR_NOALIGN);
2467 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2468 (char *) conv_str, str_size);
2471 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2474 regval_ctr_delvalue(ctr, val_name);
2475 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2476 (char *) &dword, sizeof(dword));
2479 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2482 uint8 bin_bool = (b ? 1 : 0);
2483 regval_ctr_delvalue(ctr, val_name);
2484 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2485 (char *) &bin_bool, sizeof(bin_bool));
2488 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2489 const char *multi_sz)
2491 smb_ucs2_t *conv_strs = NULL;
2494 /* a multi-sz has to have a null string terminator, i.e., the last
2495 string must be followed by two nulls */
2496 str_size = (strlen(multi_sz) + 2) * sizeof(smb_ucs2_t);
2497 conv_strs = calloc(str_size, 1);
2499 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2500 STR_TERMINATE | STR_NOALIGN);
2502 regval_ctr_delvalue(ctr, val_name);
2503 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2504 (char *) conv_strs, str_size);
2505 safe_free(conv_strs);
2509 /****************************************************************************
2510 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2512 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2513 * @return BOOL indicating success or failure
2514 ***************************************************************************/
2516 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2518 REGVAL_CTR *ctr = NULL;
2520 char *allocated_string = NULL;
2521 const char *ascii_str;
2524 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2525 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2526 ctr = &info2->data.keys[i].values;
2528 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2529 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2531 get_myfullname(longname);
2532 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2534 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2535 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2536 SAFE_FREE(allocated_string);
2538 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2539 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2540 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2541 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2542 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2543 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2544 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2545 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2546 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2548 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2549 (info2->attributes &
2550 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2552 switch (info2->attributes & 0x3) {
2554 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2557 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2560 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2563 ascii_str = "unknown";
2565 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2570 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2, GUID guid)
2573 REGVAL_CTR *ctr=NULL;
2575 /* find the DsSpooler key */
2576 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2577 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2578 ctr = &info2->data.keys[i].values;
2580 regval_ctr_delvalue(ctr, "objectGUID");
2581 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2582 (char *) &guid, sizeof(GUID));
2585 static WERROR publish_it(NT_PRINTER_INFO_LEVEL *printer)
2588 TALLOC_CTX *ctx = talloc_init("publish_it");
2589 ADS_MODLIST mods = ads_init_mods(ctx);
2590 char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2591 char *srv_dn_utf8, **srv_cn_utf8;
2594 const char *attrs[] = {"objectGUID", NULL};
2596 WERROR win_rc = WERR_OK;
2599 /* set the DsSpooler info and attributes */
2600 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2)))
2602 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2603 win_rc = mod_a_printer(*printer, 2);
2604 if (!W_ERROR_IS_OK(win_rc)) {
2605 DEBUG(3, ("err %d saving data\n",
2606 W_ERROR_V(win_rc)));
2610 /* Build the ads mods */
2611 get_local_printer_publishing_data(ctx, &mods,
2612 &printer->info_2->data);
2613 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
2614 printer->info_2->sharename);
2616 /* initial ads structure */
2618 ads = ads_init(NULL, NULL, NULL);
2620 DEBUG(3, ("ads_init() failed\n"));
2621 return WERR_SERVER_UNAVAILABLE;
2623 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2624 SAFE_FREE(ads->auth.password);
2625 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2628 /* ads_connect() will find the DC for us */
2629 ads_rc = ads_connect(ads);
2630 if (!ADS_ERR_OK(ads_rc)) {
2631 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2633 return WERR_ACCESS_DENIED;
2636 /* figure out where to publish */
2637 ads_find_machine_acct(ads, &res, global_myname());
2639 /* We use ldap_get_dn here as we need the answer
2640 * in utf8 to call ldap_explode_dn(). JRA. */
2642 srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2645 return WERR_SERVER_UNAVAILABLE;
2647 ads_msgfree(ads, res);
2648 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2650 ldap_memfree(srv_dn_utf8);
2652 return WERR_SERVER_UNAVAILABLE;
2654 /* Now convert to CH_UNIX. */
2655 if (pull_utf8_allocate((void **) &srv_dn, srv_dn_utf8) == (size_t)-1) {
2656 ldap_memfree(srv_dn_utf8);
2657 ldap_memfree(srv_cn_utf8);
2659 return WERR_SERVER_UNAVAILABLE;
2661 if (pull_utf8_allocate((void **) &srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
2662 ldap_memfree(srv_dn_utf8);
2663 ldap_memfree(srv_cn_utf8);
2666 return WERR_SERVER_UNAVAILABLE;
2669 ldap_memfree(srv_dn_utf8);
2670 ldap_memfree(srv_cn_utf8);
2672 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
2673 printer->info_2->sharename, srv_dn);
2676 SAFE_FREE(srv_cn_0);
2679 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2680 if (LDAP_ALREADY_EXISTS == ads_rc.err.rc)
2681 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx,&mods);
2683 /* retreive the guid and store it locally */
2684 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2685 ads_memfree(ads, prt_dn);
2686 ads_pull_guid(ads, res, &guid);
2687 ads_msgfree(ads, res);
2688 store_printer_guid(printer->info_2, guid);
2689 win_rc = mod_a_printer(*printer, 2);
2698 WERROR unpublish_it(NT_PRINTER_INFO_LEVEL *printer)
2703 char *prt_dn = NULL;
2706 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2707 win_rc = mod_a_printer(*printer, 2);
2708 if (!W_ERROR_IS_OK(win_rc)) {
2709 DEBUG(3, ("err %d saving data\n",
2710 W_ERROR_V(win_rc)));
2714 ads = ads_init(NULL, NULL, NULL);
2716 DEBUG(3, ("ads_init() failed\n"));
2717 return WERR_SERVER_UNAVAILABLE;
2719 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2720 SAFE_FREE(ads->auth.password);
2721 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2724 /* ads_connect() will find the DC for us */
2725 ads_rc = ads_connect(ads);
2726 if (!ADS_ERR_OK(ads_rc)) {
2727 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2729 return WERR_ACCESS_DENIED;
2732 /* remove the printer from the directory */
2733 ads_rc = ads_find_printer_on_server(ads, &res,
2734 printer->info_2->sharename, global_myname());
2735 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2736 prt_dn = ads_get_dn(ads, res);
2737 ads_msgfree(ads, res);
2738 ads_rc = ads_del_dn(ads, prt_dn);
2739 ads_memfree(ads, prt_dn);
2746 /****************************************************************************
2747 * Publish a printer in the directory
2749 * @param snum describing printer service
2750 * @return WERROR indicating status of publishing
2751 ***************************************************************************/
2753 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2755 NT_PRINTER_INFO_LEVEL *printer = NULL;
2758 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2759 if (!W_ERROR_IS_OK(win_rc))
2763 case SPOOL_DS_PUBLISH:
2764 case SPOOL_DS_UPDATE:
2765 win_rc = publish_it(printer);
2767 case SPOOL_DS_UNPUBLISH:
2768 win_rc = unpublish_it(printer);
2771 win_rc = WERR_NOT_SUPPORTED;
2775 free_a_printer(&printer, 2);
2779 BOOL is_printer_published(Printer_entry *print_hnd, int snum, GUID *guid)
2781 NT_PRINTER_INFO_LEVEL *printer = NULL;
2783 REGISTRY_VALUE *guid_val;
2788 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2789 if (!W_ERROR_IS_OK(win_rc))
2792 if (!(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
2795 if ((i = lookup_printerkey(&printer->info_2->data,
2796 SPOOL_DSSPOOLER_KEY)) < 0)
2799 if (!(ctr = &printer->info_2->data.keys[i].values)) {
2803 if (!(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
2807 if (regval_size(guid_val) == sizeof(GUID))
2808 memcpy(guid, regval_data_p(guid_val), sizeof(GUID));
2814 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2818 BOOL is_printer_published(Printer_entry *print_hnd, int snum, GUID *guid)
2823 /****************************************************************************
2824 ***************************************************************************/
2826 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
2828 NT_PRINTER_DATA *data;
2830 int removed_keys = 0;
2834 empty_slot = data->num_keys;
2837 return WERR_INVALID_PARAM;
2839 /* remove all keys */
2841 if ( !strlen(key) ) {
2842 for ( i=0; i<data->num_keys; i++ ) {
2843 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2844 data->keys[i].name));
2846 SAFE_FREE( data->keys[i].name );
2847 regval_ctr_destroy( &data->keys[i].values );
2850 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2853 SAFE_FREE( data->keys );
2854 ZERO_STRUCTP( data );
2859 /* remove a specific key (and all subkeys) */
2861 for ( i=0; i<data->num_keys; i++ ) {
2862 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
2863 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2864 data->keys[i].name));
2866 SAFE_FREE( data->keys[i].name );
2867 regval_ctr_destroy( &data->keys[i].values );
2869 /* mark the slot as empty */
2871 ZERO_STRUCTP( &data->keys[i] );
2875 /* find the first empty slot */
2877 for ( i=0; i<data->num_keys; i++ ) {
2878 if ( !data->keys[i].name ) {
2885 if ( i == data->num_keys )
2886 /* nothing was removed */
2887 return WERR_INVALID_PARAM;
2889 /* move everything down */
2891 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
2892 if ( data->keys[i].name ) {
2893 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
2894 ZERO_STRUCTP( &data->keys[i] );
2902 data->num_keys -= removed_keys;
2904 /* sanity check to see if anything is left */
2906 if ( !data->num_keys ) {
2907 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
2909 SAFE_FREE( data->keys );
2910 ZERO_STRUCTP( data );
2916 /****************************************************************************
2917 ***************************************************************************/
2919 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
2921 WERROR result = WERR_OK;
2924 /* we must have names on non-zero length */
2926 if ( !key || !*key|| !value || !*value )
2927 return WERR_INVALID_NAME;
2929 /* find the printer key first */
2931 key_index = lookup_printerkey( &p2->data, key );
2932 if ( key_index == -1 )
2935 /* make sure the value exists so we can return the correct error code */
2937 if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) )
2938 return WERR_BADFILE;
2940 regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
2942 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2948 /****************************************************************************
2949 ***************************************************************************/
2951 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
2952 uint32 type, uint8 *data, int real_len )
2954 WERROR result = WERR_OK;
2957 /* we must have names on non-zero length */
2959 if ( !key || !*key|| !value || !*value )
2960 return WERR_INVALID_NAME;
2962 /* find the printer key first */
2964 key_index = lookup_printerkey( &p2->data, key );
2965 if ( key_index == -1 )
2966 key_index = add_new_printer_key( &p2->data, key );
2968 if ( key_index == -1 )
2971 regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
2972 type, (const char *)data, real_len );
2974 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
2975 key, value, type, real_len ));
2980 /****************************************************************************
2981 ***************************************************************************/
2983 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
2987 if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
2990 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
2993 return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
2996 /****************************************************************************
2997 Unpack a list of registry values frem the TDB
2998 ***************************************************************************/
3000 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3004 pstring string, valuename, keyname;
3008 REGISTRY_VALUE *regval_p;
3011 /* add the "PrinterDriverData" key first for performance reasons */
3013 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3015 /* loop and unpack the rest of the registry values */
3019 /* check to see if there are any more registry values */
3021 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3025 /* unpack the next regval */
3027 len += tdb_unpack(buf+len, buflen-len, "fdB",
3034 * break of the keyname from the value name.
3035 * Should only be one '\' in the string returned.
3038 str = strrchr( string, '\\');
3040 /* Put in "PrinterDriverData" is no key specified */
3043 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3044 pstrcpy( valuename, string );
3048 pstrcpy( keyname, string );
3049 pstrcpy( valuename, str+1 );
3052 /* see if we need a new key */
3054 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3055 key_index = add_new_printer_key( printer_data, keyname );
3057 if ( key_index == -1 ) {
3058 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3063 /* add the new value */
3065 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3067 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3069 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3075 /****************************************************************************
3076 ***************************************************************************/
3078 static void map_to_os2_driver(fstring drivername)
3080 static BOOL initialised=False;
3081 static fstring last_from,last_to;
3082 char *mapfile = lp_os2_driver_map();
3083 char **lines = NULL;
3087 if (!strlen(drivername))
3094 *last_from = *last_to = 0;
3098 if (strequal(drivername,last_from)) {
3099 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3100 fstrcpy(drivername,last_to);
3104 lines = file_lines_load(mapfile, &numlines);
3105 if (numlines == 0) {
3106 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3110 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3112 for( i = 0; i < numlines; i++) {
3113 char *nt_name = lines[i];
3114 char *os2_name = strchr(nt_name,'=');
3121 while (isspace(*nt_name))
3124 if (!*nt_name || strchr("#;",*nt_name))
3128 int l = strlen(nt_name);
3129 while (l && isspace(nt_name[l-1])) {
3135 while (isspace(*os2_name))
3139 int l = strlen(os2_name);
3140 while (l && isspace(os2_name[l-1])) {
3146 if (strequal(nt_name,drivername)) {
3147 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3148 fstrcpy(last_from,drivername);
3149 fstrcpy(last_to,os2_name);
3150 fstrcpy(drivername,os2_name);
3151 file_lines_free(lines);
3156 file_lines_free(lines);
3159 /****************************************************************************
3160 Get a default printer info 2 struct.
3161 ****************************************************************************/
3162 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3165 NT_PRINTER_INFO_LEVEL_2 info;
3169 snum = lp_servicenumber(sharename);
3171 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3172 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
3173 get_called_name(), sharename);
3174 fstrcpy(info.sharename, sharename);
3175 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3177 /* by setting the driver name to an empty string, a local NT admin
3178 can now run the **local** APW to install a local printer driver
3179 for a Samba shared printer in 2.2. Without this, drivers **must** be
3180 installed on the Samba server for NT clients --jerry */
3181 #if 0 /* JERRY --do not uncomment-- */
3182 if (!*info.drivername)
3183 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3187 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3189 pstrcpy(info.comment, "");
3190 fstrcpy(info.printprocessor, "winprint");
3191 fstrcpy(info.datatype, "RAW");
3193 info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3195 info.starttime = 0; /* Minutes since 12:00am GMT */
3196 info.untiltime = 0; /* Minutes since 12:00am GMT */
3198 info.default_priority = 1;
3199 info.setuptime = (uint32)time(NULL);
3202 * I changed this as I think it is better to have a generic
3203 * DEVMODE than to crash Win2k explorer.exe --jerry
3204 * See the HP Deskjet 990c Win2k drivers for an example.
3206 * However the default devmode appears to cause problems
3207 * with the HP CLJ 8500 PCL driver. Hence the addition of
3208 * the "default devmode" parameter --jerry 22/01/2002
3211 if (lp_default_devmode(snum)) {
3212 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3216 info.devmode = NULL;
3219 /* This will get the current RPC talloc context, but we should be
3220 passing this as a parameter... fixme... JRA ! */
3222 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3225 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3227 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3235 free_nt_devicemode(&info.devmode);
3236 return WERR_ACCESS_DENIED;
3239 /****************************************************************************
3240 ****************************************************************************/
3241 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3244 NT_PRINTER_INFO_LEVEL_2 info;
3246 TDB_DATA kbuf, dbuf;
3247 fstring printername;
3248 char adevice[MAXDEVICENAME];
3252 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
3255 kbuf.dsize = strlen(key)+1;
3257 dbuf = tdb_fetch(tdb_printers, kbuf);
3259 return get_a_printer_2_default(info_ptr, sharename);
3261 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3264 &info.default_priority,
3281 info.printprocessor,
3285 /* Samba has to have shared raw drivers. */
3286 info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3288 /* Restore the stripped strings. */
3289 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3290 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
3292 fstrcpy(info.printername, printername);
3294 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3297 * Some client drivers freak out if there is a NULL devmode
3298 * (probably the driver is not checking before accessing
3299 * the devmode pointer) --jerry
3301 * See comments in get_a_printer_2_default()
3304 if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode) {
3305 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3307 info.devmode = construct_nt_devicemode(printername);
3310 safe_strcpy(adevice, info.printername, sizeof(adevice)-1);
3311 fstrcpy(info.devmode->devicename, adevice);
3314 len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3316 /* This will get the current RPC talloc context, but we should be
3317 passing this as a parameter... fixme... JRA ! */
3319 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3321 /* Fix for OS/2 drivers. */
3323 if (get_remote_arch() == RA_OS2)
3324 map_to_os2_driver(info.drivername);
3326 SAFE_FREE(dbuf.dptr);
3327 *info_ptr=memdup(&info, sizeof(info));
3329 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3330 sharename, info.printername, info.drivername));
3335 /****************************************************************************
3336 Debugging function, dump at level 6 the struct in the logs.
3337 ****************************************************************************/
3338 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3341 NT_PRINTER_INFO_LEVEL_2 *info2;
3343 DEBUG(106,("Dumping printer at level [%d]\n", level));
3348 if (printer.info_2 == NULL)
3352 info2=printer.info_2;
3354 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3355 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3356 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3357 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3358 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3359 DEBUGADD(106,("status:[%d]\n", info2->status));
3360 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3361 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3362 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3363 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3364 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3366 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3367 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3368 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3369 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3370 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3371 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3372 DEBUGADD(106,("location:[%s]\n", info2->location));
3373 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3374 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3375 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3376 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3382 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3390 /****************************************************************************
3391 Update the changeid time.
3392 This is SO NASTY as some drivers need this to change, others need it
3393 static. This value will change every second, and I must hope that this
3394 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3396 ****************************************************************************/
3398 static uint32 rev_changeid(void)
3402 get_process_uptime(&tv);
3405 /* Return changeid as msec since spooler restart */
3406 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3409 * This setting seems to work well but is too untested
3410 * to replace the above calculation. Left in for experiementation
3411 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3413 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3418 * The function below are the high level ones.
3419 * only those ones must be called from the spoolss code.
3423 /****************************************************************************
3424 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3425 ****************************************************************************/
3427 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3431 dump_a_printer(printer, level);
3434 * invalidate cache for all open handles to this printer.
3435 * cache for a given handle will be updated on the next
3439 invalidate_printer_hnd_cache( printer.info_2->sharename );
3445 * Update the changestamp. Emperical tests show that the
3446 * ChangeID is always updated,but c_setprinter is
3447 * global spooler variable (not per printer).
3450 /* ChangeID **must** be increasing over the lifetime
3451 of client's spoolss service in order for the
3452 client's cache to show updates */
3454 printer.info_2->changeid = rev_changeid();
3457 * Because one day someone will ask:
3458 * NT->NT An admin connection to a remote
3459 * printer show changes imeediately in
3460 * the properities dialog
3462 * A non-admin connection will only show the
3463 * changes after viewing the properites page
3464 * 2 times. Seems to be related to a
3465 * race condition in the client between the spooler
3466 * updating the local cache and the Explorer.exe GUI
3467 * actually displaying the properties.
3469 * This is fixed in Win2k. admin/non-admin
3470 * connections both display changes immediately.
3475 result=update_a_printer_2(printer.info_2);
3480 result=WERR_UNKNOWN_LEVEL;
3487 /****************************************************************************
3488 Initialize printer devmode & data with previously saved driver init values.
3489 ****************************************************************************/
3491 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3495 TDB_DATA kbuf, dbuf;
3496 NT_PRINTER_INFO_LEVEL_2 info;
3502 * Delete any printer data 'values' already set. When called for driver
3503 * replace, there will generally be some, but during an add printer, there
3504 * should not be any (if there are delete them).
3507 delete_all_printer_data( info_ptr, "" );
3509 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3512 kbuf.dsize = strlen(key)+1;
3514 dbuf = tdb_fetch(tdb_drivers, kbuf);
3517 * When changing to a driver that has no init info in the tdb, remove
3518 * the previous drivers init info and leave the new on blank.
3520 free_nt_devicemode(&info_ptr->devmode);
3525 * Get the saved DEVMODE..
3528 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3531 * The saved DEVMODE contains the devicename from the printer used during
3532 * the initialization save. Change it to reflect the new printer.
3535 if ( info.devmode ) {
3536 ZERO_STRUCT(info.devmode->devicename);
3537 fstrcpy(info.devmode->devicename, info_ptr->printername);
3541 * NT/2k does not change out the entire DeviceMode of a printer
3542 * when changing the driver. Only the driverextra, private, &
3543 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3545 * Later examination revealed that Windows NT/2k does reset the
3546 * the printer's device mode, bit **only** when you change a
3547 * property of the device mode such as the page orientation.
3552 /* Bind the saved DEVMODE to the new the printer */
3554 free_nt_devicemode(&info_ptr->devmode);
3555 info_ptr->devmode = info.devmode;
3557 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3558 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3560 /* Add the printer data 'values' to the new printer */
3562 len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3565 SAFE_FREE(dbuf.dptr);
3570 /****************************************************************************
3571 Initialize printer devmode & data with previously saved driver init values.
3572 When a printer is created using AddPrinter, the drivername bound to the
3573 printer is used to lookup previously saved driver initialization info, which
3574 is bound to the new printer.
3575 ****************************************************************************/
3577 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3579 BOOL result = False;
3583 result = set_driver_init_2(printer->info_2);
3587 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3595 /****************************************************************************
3596 Delete driver init data stored for a specified driver
3597 ****************************************************************************/
3599 BOOL del_driver_init(char *drivername)
3604 if (!drivername || !*drivername) {
3605 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3609 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3612 kbuf.dsize = strlen(key)+1;
3614 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3616 return (tdb_delete(tdb_drivers, kbuf) == 0);
3619 /****************************************************************************
3620 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3621 in the tdb. Note: this is different from the driver entry and the printer
3622 entry. There should be a single driver init entry for each driver regardless
3623 of whether it was installed from NT or 2K. Technically, they should be
3624 different, but they work out to the same struct.
3625 ****************************************************************************/
3627 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3631 int buflen, len, ret;
3632 TDB_DATA kbuf, dbuf;
3639 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3641 len += pack_values( &info->data, buf+len, buflen-len );
3643 if (buflen != len) {
3646 tb = (char *)Realloc(buf, len);
3648 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3658 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3661 kbuf.dsize = strlen(key)+1;
3665 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3669 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3673 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3674 info->sharename, info->drivername));
3679 /****************************************************************************
3680 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3681 ****************************************************************************/
3683 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3687 dump_a_printer(printer, level);
3691 result = update_driver_init_2(printer.info_2);
3701 /****************************************************************************
3702 Convert the printer data value, a REG_BINARY array, into an initialization
3703 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3704 got to keep the endians happy :).
3705 ****************************************************************************/
3707 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
3709 BOOL result = False;
3713 ZERO_STRUCT(devmode);
3715 prs_init(&ps, 0, ctx, UNMARSHALL);
3716 ps.data_p = (char *)data;
3717 ps.buffer_size = data_len;
3719 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3720 result = convert_devicemode("", &devmode, &nt_devmode);
3722 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3727 /****************************************************************************
3728 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3730 1. Use the driver's config DLL to this UNC printername and:
3731 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3732 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3733 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3735 The last step triggers saving the "driver initialization" information for
3736 this printer into the tdb. Later, new printers that use this driver will
3737 have this initialization information bound to them. This simulates the
3738 driver initialization, as if it had run on the Samba server (as it would
3741 The Win32 client side code requirement sucks! But until we can run arbitrary
3742 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3744 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3745 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3746 about it and you will realize why. JRR 010720
3747 ****************************************************************************/
3749 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
3751 WERROR status = WERR_OK;
3752 TALLOC_CTX *ctx = NULL;
3753 NT_DEVICEMODE *nt_devmode = NULL;
3754 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3757 * When the DEVMODE is already set on the printer, don't try to unpack it.
3759 DEBUG(8,("save_driver_init_2: Enter...\n"));
3761 if ( !printer->info_2->devmode && data_len ) {
3763 * Set devmode on printer info, so entire printer initialization can be
3767 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
3770 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3771 status = WERR_NOMEM;
3775 ZERO_STRUCTP(nt_devmode);
3778 * The DEVMODE is held in the 'data' component of the param in raw binary.
3779 * Convert it to to a devmode structure
3781 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
3782 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3783 status = WERR_INVALID_PARAM;
3787 printer->info_2->devmode = nt_devmode;
3791 * Pack up and add (or update) the DEVMODE and any current printer data to
3792 * a 'driver init' element in the tdb
3796 if ( update_driver_init(*printer, 2) != 0 ) {
3797 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3798 status = WERR_NOMEM;
3803 * If driver initialization info was successfully saved, set the current
3804 * printer to match it. This allows initialization of the current printer
3805 * as well as the driver.
3807 status = mod_a_printer(*printer, 2);
3808 if (!W_ERROR_IS_OK(status)) {
3809 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3810 printer->info_2->printername));
3814 talloc_destroy(ctx);
3815 free_nt_devicemode( &nt_devmode );
3817 printer->info_2->devmode = tmp_devmode;
3822 /****************************************************************************
3823 Update the driver init info (DEVMODE and specifics) for a printer
3824 ****************************************************************************/
3826 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
3828 WERROR status = WERR_OK;
3832 status = save_driver_init_2( printer, data, data_len );
3835 status = WERR_UNKNOWN_LEVEL;
3842 /****************************************************************************
3843 Deep copy a NT_PRINTER_DATA
3844 ****************************************************************************/
3846 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
3848 int i, j, num_vals, new_key_index;
3849 REGVAL_CTR *src_key, *dst_key;
3852 return NT_STATUS_NO_MEMORY;
3854 for ( i=0; i<src->num_keys; i++ ) {
3856 /* create a new instance of the printerkey in the destination
3857 printer_data object */
3859 new_key_index = add_new_printer_key( dst, src->keys[i].name );
3860 dst_key = &dst->keys[new_key_index].values;
3862 src_key = &src->keys[i].values;
3863 num_vals = regval_ctr_numvals( src_key );
3865 /* dup the printer entire printer key */
3867 for ( j=0; j<num_vals; j++ ) {
3868 regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
3872 return NT_STATUS_OK;
3875 /****************************************************************************
3876 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
3878 ****************************************************************************/
3880 NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
3882 NT_PRINTER_INFO_LEVEL_2 *copy;
3887 if ( !(copy = (NT_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2))) )
3890 memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
3892 /* malloc()'d members copied here */
3894 copy->devmode = dup_nt_devicemode( printer->devmode );
3896 ZERO_STRUCT( copy->data );
3897 copy_printer_data( ©->data, &printer->data );
3899 /* this is talloc()'d; very ugly that we have a structure that
3900 is half malloc()'d and half talloc()'d but that is the way
3901 that the PRINTER_INFO stuff is written right now. --jerry */
3903 copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
3908 /****************************************************************************
3909 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3910 ****************************************************************************/
3912 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
3913 const char *sharename)
3916 NT_PRINTER_INFO_LEVEL *printer = NULL;
3920 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3924 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3925 DEBUG(0,("get_a_printer: malloc fail.\n"));
3928 ZERO_STRUCTP(printer);
3931 * check for cache first. A Printer handle cannot changed
3932 * to another printer object so we only check that the printer
3933 * is actually for a printer and that the printer_info pointer
3937 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)
3938 && print_hnd->printer_info )
3940 if ( !(printer->info_2 = dup_printer_2(print_hnd->ctx, print_hnd->printer_info->info_2)) ) {
3941 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
3947 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
3949 *pp_printer = printer;
3955 /* no cache for this handle; see if we can match one from another handle */
3958 result = find_printer_in_print_hnd_cache(print_hnd->ctx, &printer->info_2, sharename);
3960 /* fail to disk if we don't have it with any open handle */
3962 if ( !print_hnd || !W_ERROR_IS_OK(result) )
3963 result = get_a_printer_2(&printer->info_2, sharename);
3965 /* we have a new printer now. Save it with this handle */
3967 if ( W_ERROR_IS_OK(result) ) {
3968 dump_a_printer(*printer, level);
3970 /* save a copy in cache */
3971 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
3972 if ( !print_hnd->printer_info )
3973 print_hnd->printer_info = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL));
3975 if ( print_hnd->printer_info ) {
3976 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
3978 /* don't fail the lookup just because the cache update failed */
3979 if ( !print_hnd->printer_info->info_2 )
3980 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
3983 *pp_printer = printer;
3991 result=WERR_UNKNOWN_LEVEL;
3995 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
4000 /****************************************************************************
4001 Deletes a NT_PRINTER_INFO_LEVEL struct.
4002 ****************************************************************************/
4004 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4007 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4009 DEBUG(104,("freeing a printer at level [%d]\n", level));
4011 if (printer == NULL)
4016 if (printer->info_2 != NULL) {
4017 free_nt_printer_info_level_2(&printer->info_2);
4028 SAFE_FREE(*pp_printer);
4032 /****************************************************************************
4033 ****************************************************************************/
4034 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4037 DEBUG(104,("adding a printer at level [%d]\n", level));
4038 dump_a_printer_driver(driver, level);
4042 result=add_a_printer_driver_3(driver.info_3);
4046 result=add_a_printer_driver_6(driver.info_6);
4056 /****************************************************************************
4057 ****************************************************************************/
4059 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4060 fstring drivername, const char *architecture, uint32 version)
4066 /* Sometime we just want any version of the driver */
4068 if ( version == DRIVER_ANY_VERSION ) {
4069 /* look for Win2k first and then for NT4 */
4070 result = get_a_printer_driver_3(&driver->info_3, drivername,
4073 if ( !W_ERROR_IS_OK(result) ) {
4074 result = get_a_printer_driver_3( &driver->info_3,
4075 drivername, architecture, 2 );
4078 result = get_a_printer_driver_3(&driver->info_3, drivername,
4079 architecture, version);
4088 if (W_ERROR_IS_OK(result))
4089 dump_a_printer_driver(*driver, level);
4094 /****************************************************************************
4095 ****************************************************************************/
4096 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4103 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4104 if (driver.info_3 != NULL)
4106 info3=driver.info_3;
4107 SAFE_FREE(info3->dependentfiles);
4108 ZERO_STRUCTP(info3);
4118 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4119 if (driver.info_6 != NULL) {
4120 info6=driver.info_6;
4121 SAFE_FREE(info6->dependentfiles);
4122 SAFE_FREE(info6->previousnames);
4123 ZERO_STRUCTP(info6);
4139 /****************************************************************************
4140 Determine whether or not a particular driver is currently assigned
4142 ****************************************************************************/
4144 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4147 int n_services = lp_numservices();
4148 NT_PRINTER_INFO_LEVEL *printer = NULL;
4153 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4155 /* loop through the printers.tdb and check for the drivername */
4157 for (snum=0; snum<n_services; snum++) {
4158 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4161 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4164 if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
4165 free_a_printer( &printer, 2 );
4169 free_a_printer( &printer, 2 );
4172 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4174 /* report that the driver is not in use by default */
4180 /**********************************************************************
4181 Check to see if a ogiven file is in use by *info
4182 *********************************************************************/
4184 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4191 if ( strequal(file, info->driverpath) )
4194 if ( strequal(file, info->datafile) )
4197 if ( strequal(file, info->configfile) )
4200 if ( strequal(file, info->helpfile) )
4203 /* see of there are any dependent files to examine */
4205 if ( !info->dependentfiles )
4208 while ( *info->dependentfiles[i] ) {
4209 if ( strequal(file, info->dependentfiles[i]) )
4218 /**********************************************************************
4219 Utility function to remove the dependent file pointed to by the
4220 input parameter from the list
4221 *********************************************************************/
4223 static void trim_dependent_file( fstring files[], int idx )
4226 /* bump everything down a slot */
4228 while( *files[idx+1] ) {
4229 fstrcpy( files[idx], files[idx+1] );
4238 /**********************************************************************
4239 Check if any of the files used by src are also used by drv
4240 *********************************************************************/
4242 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4243 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4245 BOOL in_use = False;
4251 /* check each file. Remove it from the src structure if it overlaps */
4253 if ( drv_file_in_use(src->driverpath, drv) ) {
4255 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4256 fstrcpy( src->driverpath, "" );
4259 if ( drv_file_in_use(src->datafile, drv) ) {
4261 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4262 fstrcpy( src->datafile, "" );
4265 if ( drv_file_in_use(src->configfile, drv) ) {
4267 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4268 fstrcpy( src->configfile, "" );
4271 if ( drv_file_in_use(src->helpfile, drv) ) {
4273 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4274 fstrcpy( src->helpfile, "" );
4277 /* are there any dependentfiles to examine? */
4279 if ( !src->dependentfiles )
4282 while ( *src->dependentfiles[i] ) {
4283 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4285 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4286 trim_dependent_file( src->dependentfiles, i );
4294 /****************************************************************************
4295 Determine whether or not a particular driver files are currently being
4296 used by any other driver.
4298 Return value is True if any files were in use by other drivers
4299 and False otherwise.
4301 Upon return, *info has been modified to only contain the driver files
4302 which are not in use
4303 ****************************************************************************/
4305 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4310 fstring *list = NULL;
4311 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4316 version = info->cversion;
4318 /* loop over all driver versions */
4320 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4322 /* get the list of drivers */
4325 ndrivers = get_ntdrivers(&list, info->environment, version);
4327 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4328 ndrivers, info->environment, version));
4330 /* check each driver for overlap in files */
4332 for (i=0; i<ndrivers; i++) {
4333 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4335 ZERO_STRUCT(driver);
4337 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4342 /* check if d2 uses any files from d1 */
4343 /* only if this is a different driver than the one being deleted */
4345 if ( !strequal(info->name, driver.info_3->name) ) {
4346 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4347 free_a_printer_driver(driver, 3);
4353 free_a_printer_driver(driver, 3);
4358 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4360 driver.info_3 = info;
4362 if ( DEBUGLEVEL >= 20 )
4363 dump_a_printer_driver( driver, 3 );
4368 /****************************************************************************
4369 Actually delete the driver files. Make sure that
4370 printer_driver_files_in_use() return False before calling
4372 ****************************************************************************/
4374 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4378 connection_struct *conn;
4386 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4389 * Connect to the print$ share under the same account as the
4390 * user connected to the rpc pipe. Note we must be root to
4394 null_pw = data_blob( NULL, 0 );
4395 fstrcpy(res_type, "A:");
4397 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4401 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4405 /* Save who we are - we are temporarily becoming the connection user. */
4407 if ( !become_user(conn, conn->vuid) ) {
4408 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4412 /* now delete the files; must strip the '\print$' string from
4415 if ( *info_3->driverpath ) {
4416 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4417 DEBUG(10,("deleting driverfile [%s]\n", s));
4418 unlink_internals(conn, 0, s);
4422 if ( *info_3->configfile ) {
4423 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4424 DEBUG(10,("deleting configfile [%s]\n", s));
4425 unlink_internals(conn, 0, s);
4429 if ( *info_3->datafile ) {
4430 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4431 DEBUG(10,("deleting datafile [%s]\n", s));
4432 unlink_internals(conn, 0, s);
4436 if ( *info_3->helpfile ) {
4437 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4438 DEBUG(10,("deleting helpfile [%s]\n", s));
4439 unlink_internals(conn, 0, s);
4443 /* check if we are done removing files */
4445 if ( info_3->dependentfiles ) {
4446 while ( *info_3->dependentfiles[i] ) {
4449 /* bypass the "\print$" portion of the path */
4451 if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4452 DEBUG(10,("deleting dependent file [%s]\n", file));
4453 unlink_internals(conn, 0, file );
4465 /****************************************************************************
4466 Remove a printer driver from the TDB. This assumes that the the driver was
4467 previously looked up.
4468 ***************************************************************************/
4470 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4471 uint32 version, BOOL delete_files )
4475 TDB_DATA kbuf, dbuf;
4476 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4478 /* delete the tdb data first */
4480 arch = get_short_archi(info_3->environment);
4481 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4482 arch, version, info_3->name);
4484 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4485 key, delete_files ? "TRUE" : "FALSE" ));
4487 ctr.info_3 = info_3;
4488 dump_a_printer_driver( ctr, 3 );
4491 kbuf.dsize=strlen(key)+1;
4493 /* check if the driver actually exists for this environment */
4495 dbuf = tdb_fetch( tdb_drivers, kbuf );
4497 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4498 return WERR_UNKNOWN_PRINTER_DRIVER;
4501 SAFE_FREE( dbuf.dptr );
4503 /* ok... the driver exists so the delete should return success */
4505 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4506 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4507 return WERR_ACCESS_DENIED;
4511 * now delete any associated files if delete_files == True
4512 * even if this part failes, we return succes because the
4513 * driver doesn not exist any more
4517 delete_driver_files( info_3, user );
4520 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4525 /****************************************************************************
4526 Store a security desc for a printer.
4527 ****************************************************************************/
4529 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4531 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4532 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4534 TALLOC_CTX *mem_ctx = NULL;
4538 mem_ctx = talloc_init("nt_printing_setsec");
4539 if (mem_ctx == NULL)
4542 /* The old owner and group sids of the security descriptor are not
4543 present when new ACEs are added or removed by changing printer
4544 permissions through NT. If they are NULL in the new security
4545 descriptor then copy them over from the old one. */
4547 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4548 DOM_SID *owner_sid, *group_sid;
4549 SEC_ACL *dacl, *sacl;
4550 SEC_DESC *psd = NULL;
4553 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4555 /* Pick out correct owner and group sids */
4557 owner_sid = secdesc_ctr->sec->owner_sid ?
4558 secdesc_ctr->sec->owner_sid :
4559 old_secdesc_ctr->sec->owner_sid;
4561 group_sid = secdesc_ctr->sec->grp_sid ?
4562 secdesc_ctr->sec->grp_sid :
4563 old_secdesc_ctr->sec->grp_sid;
4565 dacl = secdesc_ctr->sec->dacl ?
4566 secdesc_ctr->sec->dacl :
4567 old_secdesc_ctr->sec->dacl;
4569 sacl = secdesc_ctr->sec->sacl ?
4570 secdesc_ctr->sec->sacl :
4571 old_secdesc_ctr->sec->sacl;
4573 /* Make a deep copy of the security descriptor */
4575 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4576 owner_sid, group_sid,
4581 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4584 if (!new_secdesc_ctr) {
4585 new_secdesc_ctr = secdesc_ctr;
4588 /* Store the security descriptor in a tdb */
4590 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4591 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4593 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4595 status = WERR_BADFUNC;
4599 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4601 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4604 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4605 status = WERR_BADFUNC;
4608 /* Free malloc'ed memory */
4614 talloc_destroy(mem_ctx);
4618 /****************************************************************************
4619 Construct a default security descriptor buffer for a printer.
4620 ****************************************************************************/
4622 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4626 SEC_ACL *psa = NULL;
4627 SEC_DESC_BUF *sdb = NULL;
4628 SEC_DESC *psd = NULL;
4632 /* Create an ACE where Everyone is allowed to print */
4634 init_sec_access(&sa, PRINTER_ACE_PRINT);
4635 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4636 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4638 /* Make the security descriptor owned by the Administrators group
4639 on the PDC of the domain. */
4641 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4642 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4645 /* Backup plan - make printer owned by admins.
4646 This should emulate a lanman printer as security
4647 settings can't be changed. */
4649 sid_copy(&owner_sid, get_global_sam_sid());
4650 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4653 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4654 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4655 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4656 SEC_ACE_FLAG_INHERIT_ONLY);
4658 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4659 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4660 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4662 /* The ACL revision number in rpc_secdesc.h differs from the one
4663 created by NT when setting ACE entries in printer
4664 descriptors. NT4 complains about the property being edited by a
4667 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4668 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
4670 NULL, psa, &sd_size);
4674 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4678 sdb = make_sec_desc_buf(ctx, sd_size, psd);
4680 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4681 (unsigned int)sd_size));
4686 /****************************************************************************
4687 Get a security desc for a printer.
4688 ****************************************************************************/
4690 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4696 if (strlen(printername) > 2 && (temp = strchr(printername + 2, '\\'))) {
4697 printername = temp + 1;
4700 /* Fetch security descriptor from tdb */
4702 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4704 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4705 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4707 DEBUG(4,("using default secdesc for %s\n", printername));
4709 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4713 /* Save default security descriptor for later */
4715 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4716 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4718 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4719 tdb_prs_store(tdb_printers, key, &ps);
4726 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4727 this security descriptor has been created when winbindd was
4728 down. Take ownership of security descriptor. */
4730 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4733 /* Change sd owner to workgroup administrator */
4735 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4736 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4737 SEC_DESC *psd = NULL;
4742 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4744 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
4746 (*secdesc_ctr)->sec->grp_sid,
4747 (*secdesc_ctr)->sec->sacl,
4748 (*secdesc_ctr)->sec->dacl,
4751 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4753 /* Swap with other one */
4755 *secdesc_ctr = new_secdesc_ctr;
4759 nt_printing_setsec(printername, *secdesc_ctr);
4763 if (DEBUGLEVEL >= 10) {
4764 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4767 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4768 printername, the_acl->num_aces));
4770 for (i = 0; i < the_acl->num_aces; i++) {
4773 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4775 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4776 the_acl->ace[i].type, the_acl->ace[i].flags,
4777 the_acl->ace[i].info.mask));
4787 1: level not implemented
4788 2: file doesn't exist
4789 3: can't allocate memory
4790 4: can't free memory
4791 5: non existant struct
4795 A printer and a printer driver are 2 different things.
4796 NT manages them separatelly, Samba does the same.
4797 Why ? Simply because it's easier and it makes sense !
4799 Now explanation: You have 3 printers behind your samba server,
4800 2 of them are the same make and model (laser A and B). But laser B
4801 has an 3000 sheet feeder and laser A doesn't such an option.
4802 Your third printer is an old dot-matrix model for the accounting :-).
4804 If the /usr/local/samba/lib directory (default dir), you will have
4805 5 files to describe all of this.
4807 3 files for the printers (1 by printer):
4810 NTprinter_accounting
4811 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4812 NTdriver_printer model X
4813 NTdriver_printer model Y
4815 jfm: I should use this comment for the text file to explain
4816 same thing for the forms BTW.
4817 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4821 /* Convert generic access rights to printer object specific access rights.
4822 It turns out that NT4 security descriptors use generic access rights and
4823 NT5 the object specific ones. */
4825 void map_printer_permissions(SEC_DESC *sd)
4829 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4830 se_map_generic(&sd->dacl->ace[i].info.mask,
4831 &printer_generic_mapping);
4835 /****************************************************************************
4836 Check a user has permissions to perform the given operation. We use the
4837 permission constants defined in include/rpc_spoolss.h to check the various
4838 actions we perform when checking printer access.
4840 PRINTER_ACCESS_ADMINISTER:
4841 print_queue_pause, print_queue_resume, update_printer_sec,
4842 update_printer, spoolss_addprinterex_level_2,
4843 _spoolss_setprinterdata
4848 JOB_ACCESS_ADMINISTER:
4849 print_job_delete, print_job_pause, print_job_resume,
4852 ****************************************************************************/
4853 BOOL print_access_check(struct current_user *user, int snum, int access_type)
4855 SEC_DESC_BUF *secdesc = NULL;
4856 uint32 access_granted;
4860 TALLOC_CTX *mem_ctx = NULL;
4861 extern struct current_user current_user;
4863 /* If user is NULL then use the current_user structure */
4866 user = ¤t_user;
4868 /* Always allow root or printer admins to do anything */
4870 if (user->uid == 0 ||
4871 user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups)) {
4875 /* Get printer name */
4877 pname = PRINTERNAME(snum);
4879 if (!pname || !*pname) {
4884 /* Get printer security descriptor */
4886 if(!(mem_ctx = talloc_init("print_access_check"))) {
4891 nt_printing_getsec(mem_ctx, pname, &secdesc);
4893 if (access_type == JOB_ACCESS_ADMINISTER) {
4894 SEC_DESC_BUF *parent_secdesc = secdesc;
4896 /* Create a child security descriptor to check permissions
4897 against. This is because print jobs are child objects
4898 objects of a printer. */
4900 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4902 /* Now this is the bit that really confuses me. The access
4903 type needs to be changed from JOB_ACCESS_ADMINISTER to
4904 PRINTER_ACCESS_ADMINISTER for this to work. Something
4905 to do with the child (job) object becoming like a
4908 access_type = PRINTER_ACCESS_ADMINISTER;
4913 map_printer_permissions(secdesc->sec);
4915 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4916 &access_granted, &status);
4918 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4920 talloc_destroy(mem_ctx);
4928 /****************************************************************************
4929 Check the time parameters allow a print operation.
4930 *****************************************************************************/
4932 BOOL print_time_access_check(int snum)
4934 NT_PRINTER_INFO_LEVEL *printer = NULL;
4936 time_t now = time(NULL);
4940 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
4943 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
4947 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4949 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
4952 free_a_printer(&printer, 2);