2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 extern DOM_SID global_sid_World;
26 static TDB_CONTEXT *tdb_forms; /* used for forms files */
27 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
28 static TDB_CONTEXT *tdb_printers; /* used for printers files */
30 #define FORMS_PREFIX "FORMS/"
31 #define DRIVERS_PREFIX "DRIVERS/"
32 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
33 #define PRINTERS_PREFIX "PRINTERS/"
34 #define SECDESC_PREFIX "SECDESC/"
35 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
37 #define NTDRIVERS_DATABASE_VERSION_1 1
38 #define NTDRIVERS_DATABASE_VERSION_2 2
39 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
41 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
43 /* Map generic permissions to printer object specific permissions */
45 GENERIC_MAPPING printer_generic_mapping = {
52 STANDARD_MAPPING printer_std_mapping = {
59 /* Map generic permissions to print server object specific permissions */
61 GENERIC_MAPPING printserver_generic_mapping = {
68 STANDARD_MAPPING printserver_std_mapping = {
75 /* We need one default form to support our default printer. Msoft adds the
76 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
77 array index). Letter is always first, so (for the current code) additions
78 always put things in the correct order. */
79 static nt_forms_struct default_forms[] = {
80 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
81 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
83 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
84 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
85 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
86 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
87 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
88 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
89 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
91 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
92 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
93 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
94 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
95 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
96 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
97 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
98 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
99 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
100 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
101 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
102 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
103 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
104 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
105 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
106 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
107 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
108 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
109 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
110 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
111 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
112 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
113 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
114 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
115 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
116 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
117 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
118 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
119 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
120 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
121 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
122 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
123 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
124 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
125 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
126 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
127 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
128 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
130 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
131 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
132 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
133 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
134 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
135 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
136 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
137 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
138 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
139 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
140 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
141 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
142 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
143 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
144 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
145 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
146 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
147 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
148 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
149 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
150 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
151 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
152 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
153 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
154 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
155 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
156 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
157 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
158 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
159 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
160 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
161 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
162 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
163 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
164 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
165 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
166 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
167 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
168 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
169 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
170 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
171 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
172 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
173 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
174 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
175 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
176 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
177 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
178 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
179 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
180 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
181 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
182 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
183 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
184 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
185 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
186 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
187 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
188 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
189 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
190 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
191 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
192 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
193 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
194 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
195 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
196 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
197 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
200 static BOOL upgrade_to_version_3(void)
202 TDB_DATA kbuf, newkey, dbuf;
204 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
206 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
207 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
209 dbuf = tdb_fetch(tdb_drivers, kbuf);
211 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
212 DEBUG(0,("upgrade_to_version_3:moving form\n"));
213 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
214 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
217 if (tdb_delete(tdb_drivers, kbuf) != 0) {
218 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
223 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
224 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
225 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
226 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
229 if (tdb_delete(tdb_drivers, kbuf) != 0) {
230 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
235 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
236 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
237 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
238 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
241 if (tdb_delete(tdb_drivers, kbuf) != 0) {
242 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
247 SAFE_FREE(dbuf.dptr);
253 /****************************************************************************
254 Open the NT printing tdb.
255 ****************************************************************************/
257 BOOL nt_printing_init(void)
259 static pid_t local_pid;
260 char *vstring = "INFO/version";
262 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
265 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
267 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
268 lock_path("ntdrivers.tdb"), strerror(errno) ));
272 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
274 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
275 lock_path("ntprinters.tdb"), strerror(errno) ));
279 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
281 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
282 lock_path("ntforms.tdb"), strerror(errno) ));
286 local_pid = sys_getpid();
288 /* handle a Samba upgrade */
289 tdb_lock_bystring(tdb_drivers, vstring);
293 /* Cope with byte-reversed older versions of the db. */
294 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
295 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
296 /* Written on a bigendian machine with old fetch_int code. Save as le. */
297 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
298 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
299 vers_id = NTDRIVERS_DATABASE_VERSION;
302 if (vers_id != NTDRIVERS_DATABASE_VERSION) {
304 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
305 if (!upgrade_to_version_3())
308 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
310 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
313 tdb_unlock_bystring(tdb_drivers, vstring);
315 update_c_setprinter(True);
320 /*******************************************************************
321 tdb traversal function for counting printers.
322 ********************************************************************/
324 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
325 TDB_DATA data, void *context)
327 int *printer_count = (int*)context;
329 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
331 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
337 /*******************************************************************
338 Update the spooler global c_setprinter. This variable is initialized
339 when the parent smbd starts with the number of existing printers. It
340 is monotonically increased by the current number of printers *after*
341 each add or delete printer RPC. Only Microsoft knows why... JRR020119
342 ********************************************************************/
344 uint32 update_c_setprinter(BOOL initialize)
347 int32 printer_count = 0;
349 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
351 /* Traverse the tdb, counting the printers */
352 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
354 /* If initializing, set c_setprinter to current printers count
355 * otherwise, bump it by the current printer count
358 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
360 c_setprinter = printer_count;
362 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
363 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
365 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
367 return (uint32)c_setprinter;
370 /*******************************************************************
371 Get the spooler global c_setprinter, accounting for initialization.
372 ********************************************************************/
374 uint32 get_c_setprinter(void)
376 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
378 if (c_setprinter == (int32)-1)
379 c_setprinter = update_c_setprinter(True);
381 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
383 return (uint32)c_setprinter;
386 /****************************************************************************
387 Get builtin form struct list.
388 ****************************************************************************/
390 int get_builtin_ntforms(nt_forms_struct **list)
392 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
393 return sizeof(default_forms) / sizeof(default_forms[0]);
396 /****************************************************************************
397 get a builtin form struct
398 ****************************************************************************/
400 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
404 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
405 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
406 count = sizeof(default_forms) / sizeof(default_forms[0]);
407 for (i=0;i<count;i++) {
408 if (strequal(form_name,default_forms[i].name)) {
409 DEBUGADD(6,("Found builtin form %s \n", form_name));
410 memcpy(form,&default_forms[i],sizeof(*form));
418 /****************************************************************************
419 get a form struct list
420 ****************************************************************************/
421 int get_ntforms(nt_forms_struct **list)
423 TDB_DATA kbuf, newkey, dbuf;
425 nt_forms_struct form;
430 for (kbuf = tdb_firstkey(tdb_forms);
432 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
433 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
435 dbuf = tdb_fetch(tdb_forms, kbuf);
436 if (!dbuf.dptr) continue;
438 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
439 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
440 &i, &form.flag, &form.width, &form.length, &form.left,
441 &form.top, &form.right, &form.bottom);
442 SAFE_FREE(dbuf.dptr);
443 if (ret != dbuf.dsize) continue;
445 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
447 DEBUG(0,("get_ntforms: Realloc fail.\n"));
459 /****************************************************************************
460 write a form struct list
461 ****************************************************************************/
462 int write_ntforms(nt_forms_struct **list, int number)
469 for (i=0;i<number;i++) {
470 /* save index, so list is rebuilt in correct order */
471 len = tdb_pack(buf, sizeof(buf), "dddddddd",
472 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
473 (*list)[i].left, (*list)[i].top, (*list)[i].right,
475 if (len > sizeof(buf)) break;
476 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
477 kbuf.dsize = strlen(key)+1;
481 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
487 /****************************************************************************
488 add a form struct at the end of the list
489 ****************************************************************************/
490 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
498 * NT tries to add forms even when
499 * they are already in the base
500 * only update the values if already present
505 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
506 for (n=0; n<*count; n++) {
507 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
508 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
515 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
516 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
520 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
524 (*list)[n].flag=form->flags;
525 (*list)[n].width=form->size_x;
526 (*list)[n].length=form->size_y;
527 (*list)[n].left=form->left;
528 (*list)[n].top=form->top;
529 (*list)[n].right=form->right;
530 (*list)[n].bottom=form->bottom;
535 /****************************************************************************
536 delete a named form struct
537 ****************************************************************************/
538 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
547 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
549 for (n=0; n<*count; n++) {
550 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
551 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
557 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
558 *ret = WERR_INVALID_PARAM;
562 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
563 kbuf.dsize = strlen(key)+1;
565 if (tdb_delete(tdb_forms, kbuf) != 0) {
573 /****************************************************************************
575 ****************************************************************************/
576 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
580 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
582 DEBUG(106, ("[%s]\n", form_name));
583 for (n=0; n<count; n++)
585 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
586 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
590 if (n==count) return;
592 (*list)[n].flag=form->flags;
593 (*list)[n].width=form->size_x;
594 (*list)[n].length=form->size_y;
595 (*list)[n].left=form->left;
596 (*list)[n].top=form->top;
597 (*list)[n].right=form->right;
598 (*list)[n].bottom=form->bottom;
601 /****************************************************************************
602 get the nt drivers list
604 traverse the database and look-up the matching names
605 ****************************************************************************/
606 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
612 TDB_DATA kbuf, newkey;
614 get_short_archi(short_archi, architecture);
615 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
617 for (kbuf = tdb_firstkey(tdb_drivers);
619 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
620 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
622 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
623 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
628 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
635 /****************************************************************************
636 function to do the mapping between the long architecture name and
638 ****************************************************************************/
639 BOOL get_short_archi(char *short_archi, char *long_archi)
646 struct table archi_table[]=
648 {"Windows 4.0", "WIN40" },
649 {"Windows NT x86", "W32X86" },
650 {"Windows NT R4000", "W32MIPS" },
651 {"Windows NT Alpha_AXP", "W32ALPHA" },
652 {"Windows NT PowerPC", "W32PPC" },
658 DEBUG(107,("Getting architecture dependant directory\n"));
661 } while ( (archi_table[i].long_archi!=NULL ) &&
662 StrCaseCmp(long_archi, archi_table[i].long_archi) );
664 if (archi_table[i].long_archi==NULL) {
665 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
669 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
671 DEBUGADD(108,("index: [%d]\n", i));
672 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
673 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
678 /****************************************************************************
679 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
680 There are two case to be covered here: PE (Portable Executable) and NE (New
681 Executable) files. Both files support the same INFO structure, but PE files
682 store the signature in unicode, and NE files store it as !unicode.
683 returns -1 on error, 1 on version info found, and 0 on no version info found.
684 ****************************************************************************/
686 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
692 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
693 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
694 fname, PE_HEADER_SIZE));
698 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
699 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
700 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
702 goto no_version_info;
705 /* Is this really a DOS header? */
706 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
707 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
708 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
709 goto no_version_info;
712 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
713 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
714 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
716 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
717 goto no_version_info;
720 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
721 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
723 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
724 goto no_version_info;
727 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
728 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
730 int section_table_bytes;
732 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
733 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
734 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
735 /* At this point, we assume the file is in error. It still could be somthing
736 * else besides a PE file, but it unlikely at this point.
741 /* get the section table */
742 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
743 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
745 if ((buf=malloc(section_table_bytes)) == NULL) {
746 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
747 fname, section_table_bytes));
751 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
752 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
757 /* Iterate the section table looking for the resource section ".rsrc" */
758 for (i = 0; i < num_sections; i++) {
759 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
761 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
762 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
763 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
766 if ((buf=malloc(section_bytes)) == NULL) {
767 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
768 fname, section_bytes));
772 /* Seek to the start of the .rsrc section info */
773 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
774 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
779 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
780 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
785 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
786 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
787 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
788 /* Align to next long address */
789 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
791 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
792 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
793 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
795 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
796 fname, *major, *minor,
797 (*major>>16)&0xffff, *major&0xffff,
798 (*minor>>16)&0xffff, *minor&0xffff));
807 /* Version info not found, fall back to origin date/time */
808 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
812 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
813 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
814 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
815 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
816 /* At this point, we assume the file is in error. It still could be somthing
817 * else besides a NE file, but it unlikely at this point. */
821 /* Allocate a bit more space to speed up things */
823 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
824 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
825 fname, PE_HEADER_SIZE));
829 /* This is a HACK! I got tired of trying to sort through the messy
830 * 'NE' file format. If anyone wants to clean this up please have at
831 * it, but this works. 'NE' files will eventually fade away. JRR */
832 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
833 /* Cover case that should not occur in a well formed 'NE' .dll file */
834 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
836 for(i=0; i<byte_count; i++) {
837 /* Fast skip past data that can't possibly match */
838 if (buf[i] != 'V') continue;
840 /* Potential match data crosses buf boundry, move it to beginning
841 * of buf, and fill the buf with as much as it will hold. */
842 if (i>byte_count-VS_VERSION_INFO_SIZE) {
845 memcpy(buf, &buf[i], byte_count-i);
846 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
847 (byte_count-i))) < 0) {
849 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
854 byte_count = bc + (byte_count - i);
855 if (byte_count<VS_VERSION_INFO_SIZE) break;
860 /* Check that the full signature string and the magic number that
861 * follows exist (not a perfect solution, but the chances that this
862 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
863 * twice, as it is simpler to read the code. */
864 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
865 /* Compute skip alignment to next long address */
866 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
867 sizeof(VS_SIGNATURE)) & 3;
868 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
870 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
871 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
872 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
873 fname, *major, *minor,
874 (*major>>16)&0xffff, *major&0xffff,
875 (*minor>>16)&0xffff, *minor&0xffff));
882 /* Version info not found, fall back to origin date/time */
883 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
888 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
889 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
890 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
901 /****************************************************************************
902 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
903 share one or more files. During the MS installation process files are checked
904 to insure that only a newer version of a shared file is installed over an
905 older version. There are several possibilities for this comparison. If there
906 is no previous version, the new one is newer (obviously). If either file is
907 missing the version info structure, compare the creation date (on Unix use
908 the modification date). Otherwise chose the numerically larger version number.
909 ****************************************************************************/
910 static int file_version_is_newer(connection_struct *conn, fstring new_file,
913 BOOL use_version = True;
918 time_t new_create_time;
922 time_t old_create_time;
926 files_struct *fsp = NULL;
928 SMB_STRUCT_STAT stat_buf;
932 ZERO_STRUCT(stat_buf);
933 new_create_time = (time_t)0;
934 old_create_time = (time_t)0;
936 /* Get file version info (if available) for previous file (if it exists) */
937 pstrcpy(filepath, old_file);
939 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
941 fsp = open_file_shared(conn, filepath, &stat_buf,
942 SET_OPEN_MODE(DOS_OPEN_RDONLY),
943 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
944 0, 0, &access_mode, &action);
946 /* Old file not found, so by definition new file is in fact newer */
947 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
952 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
953 if (ret == -1) goto error_exit;
956 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
959 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
960 old_create_time = st.st_mtime;
961 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
964 close_file(fsp, True);
966 /* Get file version info (if available) for new file */
967 pstrcpy(filepath, new_file);
968 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
970 fsp = open_file_shared(conn, filepath, &stat_buf,
971 SET_OPEN_MODE(DOS_OPEN_RDONLY),
972 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
973 0, 0, &access_mode, &action);
975 /* New file not found, this shouldn't occur if the caller did its job */
976 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
981 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
982 if (ret == -1) goto error_exit;
985 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
988 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
989 new_create_time = st.st_mtime;
990 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
993 close_file(fsp, True);
996 /* Compare versions and choose the larger version number */
997 if (new_major > old_major ||
998 (new_major == old_major && new_minor > old_minor)) {
1000 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1004 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1009 /* Compare modification time/dates and choose the newest time/date */
1010 if (new_create_time > old_create_time) {
1011 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1015 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1022 close_file(fsp, True);
1026 /****************************************************************************
1027 Determine the correct cVersion associated with an architecture and driver
1028 ****************************************************************************/
1029 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
1030 struct current_user *user, WERROR *perr)
1038 files_struct *fsp = NULL;
1041 connection_struct *conn;
1045 *perr = WERR_INVALID_PARAM;
1047 /* If architecture is Windows 95/98/ME, the version is always 0. */
1048 if (strcmp(architecture, "WIN40") == 0) {
1049 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1055 * Connect to the print$ share under the same account as the user connected
1056 * to the rpc pipe. Note we must still be root to do this.
1059 /* Null password is ok - we are already an authenticated user... */
1060 null_pw = data_blob(NULL, 0);
1062 conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
1066 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1067 *perr = ntstatus_to_werror(nt_status);
1071 /* We are temporarily becoming the connection user. */
1072 if (!become_user(conn, conn->vuid)) {
1073 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1074 *perr = WERR_ACCESS_DENIED;
1078 /* Open the driver file (Portable Executable format) and determine the
1079 * deriver the cversion. */
1080 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1082 unix_convert(driverpath,conn,NULL,&bad_path,&st);
1084 fsp = open_file_shared(conn, driverpath, &st,
1085 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1086 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1087 0, 0, &access_mode, &action);
1089 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1090 driverpath, errno));
1091 *perr = WERR_ACCESS_DENIED;
1097 int ret = get_file_version(fsp, driverpath, &major, &minor);
1098 if (ret == -1) goto error_exit;
1101 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1106 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1107 * for more details. Version in this case is not just the version of the
1108 * file, but the version in the sense of kernal mode (2) vs. user mode
1109 * (3) drivers. Other bits of the version fields are the version info.
1112 cversion = major & 0x0000ffff;
1114 case 2: /* WinNT drivers */
1115 case 3: /* Win2K drivers */
1119 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1120 driverpath, cversion));
1124 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1125 driverpath, major, minor));
1128 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1129 driverpath, cversion));
1131 close_file(fsp, True);
1132 close_cnum(conn, user->vuid);
1141 close_file(fsp, True);
1143 close_cnum(conn, user->vuid);
1148 /****************************************************************************
1149 ****************************************************************************/
1150 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1151 struct current_user *user)
1153 fstring architecture;
1159 /* clean up the driver name.
1160 * we can get .\driver.dll
1161 * or worse c:\windows\system\driver.dll !
1163 /* using an intermediate string to not have overlaping memcpy()'s */
1164 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1165 fstrcpy(new_name, p+1);
1166 fstrcpy(driver->driverpath, new_name);
1169 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1170 fstrcpy(new_name, p+1);
1171 fstrcpy(driver->datafile, new_name);
1174 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1175 fstrcpy(new_name, p+1);
1176 fstrcpy(driver->configfile, new_name);
1179 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1180 fstrcpy(new_name, p+1);
1181 fstrcpy(driver->helpfile, new_name);
1184 if (driver->dependentfiles) {
1185 for (i=0; *driver->dependentfiles[i]; i++) {
1186 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1187 fstrcpy(new_name, p+1);
1188 fstrcpy(driver->dependentfiles[i], new_name);
1193 get_short_archi(architecture, driver->environment);
1195 /* jfm:7/16/2000 the client always sends the cversion=0.
1196 * The server should check which version the driver is by reading
1197 * the PE header of driver->driverpath.
1199 * For Windows 95/98 the version is 0 (so the value sent is correct)
1200 * For Windows NT (the architecture doesn't matter)
1201 * NT 3.1: cversion=0
1202 * NT 3.5/3.51: cversion=1
1206 if ((driver->cversion = get_correct_cversion( architecture,
1207 driver->driverpath, user, &err)) == -1)
1213 /****************************************************************************
1214 ****************************************************************************/
1215 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
1216 struct current_user *user)
1218 fstring architecture;
1224 /* clean up the driver name.
1225 * we can get .\driver.dll
1226 * or worse c:\windows\system\driver.dll !
1228 /* using an intermediate string to not have overlaping memcpy()'s */
1229 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1230 fstrcpy(new_name, p+1);
1231 fstrcpy(driver->driverpath, new_name);
1234 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1235 fstrcpy(new_name, p+1);
1236 fstrcpy(driver->datafile, new_name);
1239 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1240 fstrcpy(new_name, p+1);
1241 fstrcpy(driver->configfile, new_name);
1244 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1245 fstrcpy(new_name, p+1);
1246 fstrcpy(driver->helpfile, new_name);
1249 if (driver->dependentfiles) {
1250 for (i=0; *driver->dependentfiles[i]; i++) {
1251 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1252 fstrcpy(new_name, p+1);
1253 fstrcpy(driver->dependentfiles[i], new_name);
1258 get_short_archi(architecture, driver->environment);
1260 /* jfm:7/16/2000 the client always sends the cversion=0.
1261 * The server should check which version the driver is by reading
1262 * the PE header of driver->driverpath.
1264 * For Windows 95/98 the version is 0 (so the value sent is correct)
1265 * For Windows NT (the architecture doesn't matter)
1266 * NT 3.1: cversion=0
1267 * NT 3.5/3.51: cversion=1
1271 if ((driver->version = get_correct_cversion(architecture,
1272 driver->driverpath, user, &err)) == -1)
1278 /****************************************************************************
1279 ****************************************************************************/
1280 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1281 uint32 level, struct current_user *user)
1286 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1287 driver=driver_abstract.info_3;
1288 return clean_up_driver_struct_level_3(driver, user);
1292 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1293 driver=driver_abstract.info_6;
1294 return clean_up_driver_struct_level_6(driver, user);
1297 return WERR_INVALID_PARAM;
1301 /****************************************************************************
1302 This function sucks and should be replaced. JRA.
1303 ****************************************************************************/
1305 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1307 dst->cversion = src->version;
1309 fstrcpy( dst->name, src->name);
1310 fstrcpy( dst->environment, src->environment);
1311 fstrcpy( dst->driverpath, src->driverpath);
1312 fstrcpy( dst->datafile, src->datafile);
1313 fstrcpy( dst->configfile, src->configfile);
1314 fstrcpy( dst->helpfile, src->helpfile);
1315 fstrcpy( dst->monitorname, src->monitorname);
1316 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1317 dst->dependentfiles = src->dependentfiles;
1320 #if 0 /* Debugging function */
1322 static char* ffmt(unsigned char *c){
1324 static char ffmt_str[17];
1326 for (i=0; i<16; i++) {
1327 if ((c[i] < ' ') || (c[i] > '~'))
1338 /****************************************************************************
1339 ****************************************************************************/
1340 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1341 struct current_user *user, WERROR *perr)
1343 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1344 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1345 fstring architecture;
1350 connection_struct *conn;
1357 memset(inbuf, '\0', sizeof(inbuf));
1358 memset(outbuf, '\0', sizeof(outbuf));
1362 driver=driver_abstract.info_3;
1363 else if (level==6) {
1364 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1365 driver = &converted_driver;
1367 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1371 get_short_archi(architecture, driver->environment);
1374 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1375 * Note we must be root to do this.
1379 null_pw = data_blob(NULL, 0);
1380 conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
1384 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1385 *perr = ntstatus_to_werror(nt_status);
1390 * Save who we are - we are temporarily becoming the connection user.
1393 if (!become_user(conn, conn->vuid)) {
1394 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1399 * make the directories version and version\driver_name
1400 * under the architecture directory.
1402 DEBUG(5,("Creating first directory\n"));
1403 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1404 mkdir_internal(conn, new_dir);
1406 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1407 * listed for this driver which has already been moved, skip it (note:
1408 * drivers may list the same file name several times. Then check if the
1409 * file already exists in archi\cversion\, if so, check that the version
1410 * info (or time stamps if version info is unavailable) is newer (or the
1411 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1412 * Otherwise, delete the file.
1414 * If a file is not moved to archi\cversion\ because of an error, all the
1415 * rest of the 'unmoved' driver files are removed from archi\. If one or
1416 * more of the driver's files was already moved to archi\cversion\, it
1417 * potentially leaves the driver in a partially updated state. Version
1418 * trauma will most likely occur if an client attempts to use any printer
1419 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1420 * done is appropriate... later JRR
1423 DEBUG(5,("Moving files now !\n"));
1425 if (driver->driverpath && strlen(driver->driverpath)) {
1426 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1427 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1428 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1430 status = rename_internals(conn, new_name, old_name, True);
1431 if (!NT_STATUS_IS_OK(status)) {
1432 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1433 new_name, old_name));
1434 *perr = ntstatus_to_werror(status);
1435 unlink_internals(conn, 0, new_name);
1440 unlink_internals(conn, 0, new_name);
1443 if (driver->datafile && strlen(driver->datafile)) {
1444 if (!strequal(driver->datafile, driver->driverpath)) {
1445 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1446 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1447 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1449 status = rename_internals(conn, new_name, old_name, True);
1450 if (!NT_STATUS_IS_OK(status)) {
1451 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1452 new_name, old_name));
1453 *perr = ntstatus_to_werror(status);
1454 unlink_internals(conn, 0, new_name);
1459 unlink_internals(conn, 0, new_name);
1463 if (driver->configfile && strlen(driver->configfile)) {
1464 if (!strequal(driver->configfile, driver->driverpath) &&
1465 !strequal(driver->configfile, driver->datafile)) {
1466 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1467 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1468 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1470 status = rename_internals(conn, new_name, old_name, True);
1471 if (!NT_STATUS_IS_OK(status)) {
1472 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1473 new_name, old_name));
1474 *perr = ntstatus_to_werror(status);
1475 unlink_internals(conn, 0, new_name);
1480 unlink_internals(conn, 0, new_name);
1484 if (driver->helpfile && strlen(driver->helpfile)) {
1485 if (!strequal(driver->helpfile, driver->driverpath) &&
1486 !strequal(driver->helpfile, driver->datafile) &&
1487 !strequal(driver->helpfile, driver->configfile)) {
1488 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1489 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1490 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1492 status = rename_internals(conn, new_name, old_name, True);
1493 if (!NT_STATUS_IS_OK(status)) {
1494 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1495 new_name, old_name));
1496 *perr = ntstatus_to_werror(status);
1497 unlink_internals(conn, 0, new_name);
1502 unlink_internals(conn, 0, new_name);
1506 if (driver->dependentfiles) {
1507 for (i=0; *driver->dependentfiles[i]; i++) {
1508 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1509 !strequal(driver->dependentfiles[i], driver->datafile) &&
1510 !strequal(driver->dependentfiles[i], driver->configfile) &&
1511 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1513 for (j=0; j < i; j++) {
1514 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1519 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1520 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1521 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1523 status = rename_internals(conn, new_name, old_name, True);
1524 if (!NT_STATUS_IS_OK(status)) {
1525 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1526 new_name, old_name));
1527 *perr = ntstatus_to_werror(status);
1528 unlink_internals(conn, 0, new_name);
1533 unlink_internals(conn, 0, new_name);
1539 close_cnum(conn, user->vuid);
1542 return ver == -1 ? False : True;
1545 /****************************************************************************
1546 ****************************************************************************/
1547 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1550 fstring architecture;
1556 TDB_DATA kbuf, dbuf;
1558 get_short_archi(architecture, driver->environment);
1560 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1561 * \\server is added in the rpc server layer.
1562 * It does make sense to NOT store the server's name in the printer TDB.
1565 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1567 /* .inf files do not always list a file for each of the four standard files.
1568 * Don't prepend a path to a null filename, or client claims:
1569 * "The server on which the printer resides does not have a suitable
1570 * <printer driver name> printer driver installed. Click OK if you
1571 * wish to install the driver on your local machine."
1573 if (strlen(driver->driverpath)) {
1574 fstrcpy(temp_name, driver->driverpath);
1575 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1578 if (strlen(driver->datafile)) {
1579 fstrcpy(temp_name, driver->datafile);
1580 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1583 if (strlen(driver->configfile)) {
1584 fstrcpy(temp_name, driver->configfile);
1585 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1588 if (strlen(driver->helpfile)) {
1589 fstrcpy(temp_name, driver->helpfile);
1590 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1593 if (driver->dependentfiles) {
1594 for (i=0; *driver->dependentfiles[i]; i++) {
1595 fstrcpy(temp_name, driver->dependentfiles[i]);
1596 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1600 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1602 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1609 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1612 driver->environment,
1617 driver->monitorname,
1618 driver->defaultdatatype);
1620 if (driver->dependentfiles) {
1621 for (i=0; *driver->dependentfiles[i]; i++) {
1622 len += tdb_pack(buf+len, buflen-len, "f",
1623 driver->dependentfiles[i]);
1627 if (len != buflen) {
1630 tb = (char *)Realloc(buf, len);
1632 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1643 kbuf.dsize = strlen(key)+1;
1647 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1651 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1657 /****************************************************************************
1658 ****************************************************************************/
1659 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1661 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1664 info3.cversion = driver->version;
1665 fstrcpy(info3.name,driver->name);
1666 fstrcpy(info3.environment,driver->environment);
1667 fstrcpy(info3.driverpath,driver->driverpath);
1668 fstrcpy(info3.datafile,driver->datafile);
1669 fstrcpy(info3.configfile,driver->configfile);
1670 fstrcpy(info3.helpfile,driver->helpfile);
1671 fstrcpy(info3.monitorname,driver->monitorname);
1672 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1673 info3.dependentfiles = driver->dependentfiles;
1675 return add_a_printer_driver_3(&info3);
1679 /****************************************************************************
1680 ****************************************************************************/
1681 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1683 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1687 fstrcpy(info.name, in_prt);
1688 fstrcpy(info.defaultdatatype, "RAW");
1690 fstrcpy(info.driverpath, "");
1691 fstrcpy(info.datafile, "");
1692 fstrcpy(info.configfile, "");
1693 fstrcpy(info.helpfile, "");
1695 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1698 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1699 fstrcpy(info.dependentfiles[0], "");
1701 *info_ptr = memdup(&info, sizeof(info));
1706 /****************************************************************************
1707 ****************************************************************************/
1708 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1710 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1711 TDB_DATA kbuf, dbuf;
1712 fstring architecture;
1717 ZERO_STRUCT(driver);
1719 get_short_archi(architecture, in_arch);
1721 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1723 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1726 kbuf.dsize = strlen(key)+1;
1728 dbuf = tdb_fetch(tdb_drivers, kbuf);
1730 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1732 if (!dbuf.dptr) return WERR_ACCESS_DENIED;
1734 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1743 driver.defaultdatatype);
1746 while (len < dbuf.dsize) {
1749 tddfs = (fstring *)Realloc(driver.dependentfiles,
1750 sizeof(fstring)*(i+2));
1751 if (tddfs == NULL) {
1752 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1755 else driver.dependentfiles = tddfs;
1757 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1758 &driver.dependentfiles[i]);
1761 if (driver.dependentfiles != NULL)
1762 fstrcpy(driver.dependentfiles[i], "");
1764 SAFE_FREE(dbuf.dptr);
1766 if (len != dbuf.dsize) {
1767 SAFE_FREE(driver.dependentfiles);
1769 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1772 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1777 /****************************************************************************
1778 ****************************************************************************/
1779 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1781 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1787 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1788 DEBUG(10,("driver key: [%s]\n", key));
1791 kbuf.dsize = strlen(key)+1;
1792 if (!tdb_exists(tdb_drivers, kbuf))
1796 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1798 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1799 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1800 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1801 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1802 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1803 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1804 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1806 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1807 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1808 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1810 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1811 trim_string(info3->driverpath, "\\print$\\WIN40\\0\\", 0);
1812 pstrcat(line, info3->driverpath);
1814 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1815 pstrcat(line, info3->datafile);
1817 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1818 pstrcat(line, info3->helpfile);
1820 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1821 pstrcat(line, info3->monitorname);
1823 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1826 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1828 pstrcat(line, ","); /* don't end in a "," */
1829 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1830 pstrcat(line, info3->dependentfiles[i]);
1838 /****************************************************************************
1839 Debugging function, dump at level 6 the struct in the logs.
1840 ****************************************************************************/
1842 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1845 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1848 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1854 if (driver.info_3 == NULL)
1857 info3=driver.info_3;
1859 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1860 DEBUGADD(106,("name:[%s]\n", info3->name));
1861 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1862 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1863 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1864 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1865 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1866 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1867 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1869 for (i=0; info3->dependentfiles &&
1870 *info3->dependentfiles[i]; i++) {
1871 DEBUGADD(106,("dependentfile:[%s]\n",
1872 info3->dependentfiles[i]));
1879 DEBUGADD(106,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1887 /****************************************************************************
1888 ****************************************************************************/
1889 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1893 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1895 if (!nt_devmode) return len;
1897 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1898 nt_devmode->devicename,
1899 nt_devmode->formname,
1901 nt_devmode->specversion,
1902 nt_devmode->driverversion,
1904 nt_devmode->driverextra,
1905 nt_devmode->orientation,
1906 nt_devmode->papersize,
1907 nt_devmode->paperlength,
1908 nt_devmode->paperwidth,
1911 nt_devmode->defaultsource,
1912 nt_devmode->printquality,
1915 nt_devmode->yresolution,
1916 nt_devmode->ttoption,
1917 nt_devmode->collate,
1918 nt_devmode->logpixels,
1921 nt_devmode->bitsperpel,
1922 nt_devmode->pelswidth,
1923 nt_devmode->pelsheight,
1924 nt_devmode->displayflags,
1925 nt_devmode->displayfrequency,
1926 nt_devmode->icmmethod,
1927 nt_devmode->icmintent,
1928 nt_devmode->mediatype,
1929 nt_devmode->dithertype,
1930 nt_devmode->reserved1,
1931 nt_devmode->reserved2,
1932 nt_devmode->panningwidth,
1933 nt_devmode->panningheight,
1934 nt_devmode->private);
1937 if (nt_devmode->private) {
1938 len += tdb_pack(buf+len, buflen-len, "B",
1939 nt_devmode->driverextra,
1940 nt_devmode->private);
1943 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1948 /****************************************************************************
1949 ****************************************************************************/
1950 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1954 while (param != NULL) {
1955 len += tdb_pack(buf+len, buflen-len, "pfdB",
1964 len += tdb_pack(buf+len, buflen-len, "p", param);
1970 /****************************************************************************
1971 Delete a printer - this just deletes the printer info file, any open
1972 handles are not affected.
1973 ****************************************************************************/
1975 uint32 del_a_printer(char *sharename)
1980 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1983 kbuf.dsize=strlen(key)+1;
1985 tdb_delete(tdb_printers, kbuf);
1989 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
1990 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1991 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1992 /****************************************************************************
1993 ****************************************************************************/
1994 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2000 TDB_DATA kbuf, dbuf;
2003 * in addprinter: no servername and the printer is the name
2004 * in setprinter: servername is \\server
2005 * and printer is \\server\\printer
2007 * Samba manages only local printers.
2008 * we currently don't support things like path=\\other_server\printer
2011 if (info->servername[0]!='\0') {
2012 trim_string(info->printername, info->servername, NULL);
2013 trim_string(info->printername, "\\", NULL);
2014 info->servername[0]='\0';
2018 * JFM: one day I'll forget.
2019 * below that's info->portname because that's the SAMBA sharename
2020 * and I made NT 'thinks' it's the portname
2021 * the info->sharename is the thing you can name when you add a printer
2022 * that's the short-name when you create shared printer for 95/98
2023 * So I've made a limitation in SAMBA: you can only have 1 printer model
2024 * behind a SAMBA share.
2032 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2035 info->default_priority,
2052 info->printprocessor,
2056 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2058 len += pack_specifics(info->specific, buf+len, buflen-len);
2060 if (buflen != len) {
2063 tb = (char *)Realloc(buf, len);
2065 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2075 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2078 kbuf.dsize = strlen(key)+1;
2082 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2085 if (!W_ERROR_IS_OK(ret))
2086 DEBUG(8, ("error updating printer to tdb on disk\n"));
2090 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2091 info->sharename, info->drivername, info->portname, len));
2097 /****************************************************************************
2098 ****************************************************************************/
2099 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
2101 NT_PRINTER_PARAM *current;
2103 DEBUG(108,("add_a_specific_param\n"));
2105 (*param)->next=NULL;
2107 if (info_2->specific == NULL)
2109 info_2->specific=*param;
2113 current=info_2->specific;
2114 while (current->next != NULL) {
2115 current=current->next;
2117 current->next=*param;
2123 /****************************************************************************
2124 ****************************************************************************/
2125 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
2127 NT_PRINTER_PARAM *current;
2128 NT_PRINTER_PARAM *previous;
2130 current=info_2->specific;
2133 if (current==NULL) return (False);
2135 if ( !strcmp(current->value, param->value) &&
2136 (strlen(current->value)==strlen(param->value)) ) {
2137 DEBUG(109,("deleting first value\n"));
2138 info_2->specific=current->next;
2139 SAFE_FREE(current->data);
2141 DEBUG(109,("deleted first value\n"));
2145 current=previous->next;
2147 while ( current!=NULL ) {
2148 if (!strcmp(current->value, param->value) &&
2149 strlen(current->value)==strlen(param->value) ) {
2150 DEBUG(109,("deleting current value\n"));
2151 previous->next=current->next;
2152 SAFE_FREE(current->data);
2154 DEBUG(109,("deleted current value\n"));
2158 previous=previous->next;
2159 current=current->next;
2164 /****************************************************************************
2165 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2166 ****************************************************************************/
2167 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2169 NT_PRINTER_PARAM *param = *param_ptr;
2174 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2176 SAFE_FREE(param->data);
2177 SAFE_FREE(*param_ptr);
2180 /****************************************************************************
2181 Malloc and return an NT devicemode.
2182 ****************************************************************************/
2184 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2188 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2190 if (nt_devmode == NULL) {
2191 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2195 ZERO_STRUCTP(nt_devmode);
2197 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2198 fstrcpy(nt_devmode->devicename, adevice);
2200 fstrcpy(nt_devmode->formname, "Letter");
2202 nt_devmode->specversion = 0x0401;
2203 nt_devmode->driverversion = 0x0400;
2204 nt_devmode->size = 0x00DC;
2205 nt_devmode->driverextra = 0x0000;
2206 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2207 DEFAULTSOURCE | COPIES | SCALE |
2208 PAPERSIZE | ORIENTATION;
2209 nt_devmode->orientation = 1;
2210 nt_devmode->papersize = PAPER_LETTER;
2211 nt_devmode->paperlength = 0;
2212 nt_devmode->paperwidth = 0;
2213 nt_devmode->scale = 0x64;
2214 nt_devmode->copies = 1;
2215 nt_devmode->defaultsource = BIN_FORMSOURCE;
2216 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2217 nt_devmode->color = COLOR_MONOCHROME;
2218 nt_devmode->duplex = DUP_SIMPLEX;
2219 nt_devmode->yresolution = 0;
2220 nt_devmode->ttoption = TT_SUBDEV;
2221 nt_devmode->collate = COLLATE_FALSE;
2222 nt_devmode->icmmethod = 0;
2223 nt_devmode->icmintent = 0;
2224 nt_devmode->mediatype = 0;
2225 nt_devmode->dithertype = 0;
2227 /* non utilisés par un driver d'imprimante */
2228 nt_devmode->logpixels = 0;
2229 nt_devmode->bitsperpel = 0;
2230 nt_devmode->pelswidth = 0;
2231 nt_devmode->pelsheight = 0;
2232 nt_devmode->displayflags = 0;
2233 nt_devmode->displayfrequency = 0;
2234 nt_devmode->reserved1 = 0;
2235 nt_devmode->reserved2 = 0;
2236 nt_devmode->panningwidth = 0;
2237 nt_devmode->panningheight = 0;
2239 nt_devmode->private = NULL;
2243 /****************************************************************************
2244 Deepcopy an NT devicemode.
2245 ****************************************************************************/
2247 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2249 NT_DEVICEMODE *new_nt_devicemode = NULL;
2251 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2252 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2256 new_nt_devicemode->private = NULL;
2257 if (nt_devicemode->private != NULL) {
2258 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2259 SAFE_FREE(new_nt_devicemode);
2260 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2265 return new_nt_devicemode;
2268 /****************************************************************************
2269 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2270 ****************************************************************************/
2272 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2274 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2276 if(nt_devmode == NULL)
2279 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2281 SAFE_FREE(nt_devmode->private);
2282 SAFE_FREE(*devmode_ptr);
2285 /****************************************************************************
2286 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2287 ****************************************************************************/
2288 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2290 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2291 NT_PRINTER_PARAM *param_ptr;
2296 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2298 free_nt_devicemode(&info->devmode);
2300 for(param_ptr = info->specific; param_ptr; ) {
2301 NT_PRINTER_PARAM *tofree = param_ptr;
2303 param_ptr = param_ptr->next;
2304 free_nt_printer_param(&tofree);
2307 SAFE_FREE(*info_ptr);
2311 /****************************************************************************
2312 ****************************************************************************/
2313 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2317 NT_DEVICEMODE devmode;
2319 ZERO_STRUCT(devmode);
2321 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2323 if (!*nt_devmode) return len;
2325 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2329 &devmode.specversion,
2330 &devmode.driverversion,
2332 &devmode.driverextra,
2333 &devmode.orientation,
2335 &devmode.paperlength,
2336 &devmode.paperwidth,
2339 &devmode.defaultsource,
2340 &devmode.printquality,
2343 &devmode.yresolution,
2349 &devmode.bitsperpel,
2351 &devmode.pelsheight,
2352 &devmode.displayflags,
2353 &devmode.displayfrequency,
2357 &devmode.dithertype,
2360 &devmode.panningwidth,
2361 &devmode.panningheight,
2364 if (devmode.private) {
2365 /* the len in tdb_unpack is an int value and
2366 * devmode.driverextra is only a short
2368 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2369 devmode.driverextra=(uint16)extra_len;
2371 /* check to catch an invalid TDB entry so we don't segfault */
2372 if (devmode.driverextra == 0) {
2373 devmode.private = NULL;
2377 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2379 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2380 if (devmode.private)
2381 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2386 /****************************************************************************
2387 ****************************************************************************/
2388 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2391 NT_PRINTER_PARAM param, *p;
2396 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2399 len += tdb_unpack(buf+len, buflen-len, "fdB",
2405 *list = memdup(¶m, sizeof(param));
2407 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2413 static void map_to_os2_driver(fstring drivername)
2415 static BOOL initialised=False;
2416 static fstring last_from,last_to;
2417 char *mapfile = lp_os2_driver_map();
2418 char **lines = NULL;
2422 if (!strlen(drivername))
2429 *last_from = *last_to = 0;
2433 if (strequal(drivername,last_from)) {
2434 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2435 fstrcpy(drivername,last_to);
2439 lines = file_lines_load(mapfile, &numlines);
2440 if (numlines == 0) {
2441 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2445 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2447 for( i = 0; i < numlines; i++) {
2448 char *nt_name = lines[i];
2449 char *os2_name = strchr(nt_name,'=');
2456 while (isspace(*nt_name))
2459 if (!*nt_name || strchr("#;",*nt_name))
2463 int l = strlen(nt_name);
2464 while (l && isspace(nt_name[l-1])) {
2470 while (isspace(*os2_name))
2474 int l = strlen(os2_name);
2475 while (l && isspace(os2_name[l-1])) {
2481 if (strequal(nt_name,drivername)) {
2482 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2483 fstrcpy(last_from,drivername);
2484 fstrcpy(last_to,os2_name);
2485 fstrcpy(drivername,os2_name);
2486 file_lines_free(lines);
2491 file_lines_free(lines);
2494 /****************************************************************************
2495 get a default printer info 2 struct
2496 ****************************************************************************/
2497 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2500 NT_PRINTER_INFO_LEVEL_2 info;
2504 snum = lp_servicenumber(sharename);
2506 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2507 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2508 get_called_name(), sharename);
2509 fstrcpy(info.sharename, sharename);
2510 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2511 fstrcpy(info.drivername, lp_printerdriver(snum));
2513 /* by setting the driver name to an empty string, a local NT admin
2514 can now run the **local** APW to install a local printer driver
2515 for a Samba shared printer in 2.2. Without this, drivers **must** be
2516 installed on the Samba server for NT clients --jerry */
2517 #if 0 /* JERRY --do not uncomment-- */
2518 if (!*info.drivername)
2519 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2523 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2525 pstrcpy(info.comment, "");
2526 fstrcpy(info.printprocessor, "winprint");
2527 fstrcpy(info.datatype, "RAW");
2529 info.attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK; /* attributes */
2531 info.starttime = 0; /* Minutes since 12:00am GMT */
2532 info.untiltime = 0; /* Minutes since 12:00am GMT */
2534 info.default_priority = 1;
2535 info.setuptime = (uint32)time(NULL);
2538 * I changed this as I think it is better to have a generic
2539 * DEVMODE than to crash Win2k explorer.exe --jerry
2540 * See the HP Deskjet 990c Win2k drivers for an example.
2542 * However the default devmode appears to cause problems
2543 * with the HP CLJ 8500 PCL driver. Hence the addition of
2544 * the "default devmode" parameter --jerry 22/01/2002
2547 if (lp_default_devmode(snum)) {
2548 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2552 info.devmode = NULL;
2555 /* This will get the current RPC talloc context, but we should be
2556 passing this as a parameter... fixme... JRA ! */
2558 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2561 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2563 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2571 free_nt_devicemode(&info.devmode);
2572 return WERR_ACCESS_DENIED;
2575 /****************************************************************************
2576 ****************************************************************************/
2577 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2580 NT_PRINTER_INFO_LEVEL_2 info;
2582 TDB_DATA kbuf, dbuf;
2583 fstring printername;
2587 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2590 kbuf.dsize = strlen(key)+1;
2592 dbuf = tdb_fetch(tdb_printers, kbuf);
2594 return get_a_printer_2_default(info_ptr, sharename);
2596 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2599 &info.default_priority,
2616 info.printprocessor,
2620 /* Samba has to have shared raw drivers. */
2621 info.attributes |= (PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK);
2623 /* Restore the stripped strings. */
2624 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2625 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
2627 fstrcpy(info.printername, printername);
2629 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2632 * Some client drivers freak out if there is a NULL devmode
2633 * (probably the driver is not checking before accessing
2634 * the devmode pointer) --jerry
2636 * See comments in get_a_printer_2_default()
2639 if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode)
2641 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
2643 info.devmode = construct_nt_devicemode(printername);
2646 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2648 /* This will get the current RPC talloc context, but we should be
2649 passing this as a parameter... fixme... JRA ! */
2651 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2653 /* Fix for OS/2 drivers. */
2655 if (get_remote_arch() == RA_OS2)
2656 map_to_os2_driver(info.drivername);
2658 SAFE_FREE(dbuf.dptr);
2659 *info_ptr=memdup(&info, sizeof(info));
2661 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2662 sharename, info.printername, info.drivername));
2667 /****************************************************************************
2668 debugging function, dump at level 6 the struct in the logs
2669 ****************************************************************************/
2670 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2673 NT_PRINTER_INFO_LEVEL_2 *info2;
2675 DEBUG(106,("Dumping printer at level [%d]\n", level));
2681 if (printer.info_2 == NULL)
2685 info2=printer.info_2;
2687 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2688 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2689 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2690 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2691 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2692 DEBUGADD(106,("status:[%d]\n", info2->status));
2693 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2694 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2695 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2696 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2697 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2699 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2700 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2701 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2702 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2703 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2704 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2705 DEBUGADD(106,("location:[%s]\n", info2->location));
2706 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2707 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2708 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2709 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2715 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
2723 /****************************************************************************
2724 Get the parameters we can substitute in an NT print job.
2725 ****************************************************************************/
2727 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2729 NT_PRINTER_INFO_LEVEL *printer = NULL;
2731 **printername = **sharename = **portname = '\0';
2733 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2736 fstrcpy(*printername, printer->info_2->printername);
2737 fstrcpy(*sharename, printer->info_2->sharename);
2738 fstrcpy(*portname, printer->info_2->portname);
2740 free_a_printer(&printer, 2);
2743 /****************************************************************************
2744 Update the changeid time.
2745 This is SO NASTY as some drivers need this to change, others need it
2746 static. This value will change every second, and I must hope that this
2747 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
2749 ****************************************************************************/
2751 static uint32 rev_changeid(void)
2755 get_process_uptime(&tv);
2758 /* Return changeid as msec since spooler restart */
2759 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
2762 * This setting seems to work well but is too untested
2763 * to replace the above calculation. Left in for experiementation
2764 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
2766 return tv.tv_sec * 10 + tv.tv_usec / 100000;
2771 * The function below are the high level ones.
2772 * only those ones must be called from the spoolss code.
2776 /****************************************************************************
2777 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2778 ****************************************************************************/
2780 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2784 dump_a_printer(printer, level);
2791 * Update the changestamp. Emperical tests show that the
2792 * ChangeID is always updated,but c_setprinter is
2793 * global spooler variable (not per printer).
2796 /* ChangeID **must** be increasing over the lifetime
2797 of client's spoolss service in order for the
2798 client's cache to show updates */
2800 printer.info_2->changeid = rev_changeid();
2803 * Because one day someone will ask:
2804 * NT->NT An admin connection to a remote
2805 * printer show changes imeediately in
2806 * the properities dialog
2808 * A non-admin connection will only show the
2809 * changes after viewing the properites page
2810 * 2 times. Seems to be related to a
2811 * race condition in the client between the spooler
2812 * updating the local cache and the Explorer.exe GUI
2813 * actually displaying the properties.
2815 * This is fixed in Win2k. admin/non-admin
2816 * connections both display changes immediately.
2821 result=update_a_printer_2(printer.info_2);
2825 result=WERR_UNKNOWN_LEVEL;
2832 /****************************************************************************
2833 Initialize printer devmode & data with previously saved driver init values.
2834 ****************************************************************************/
2836 static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
2840 TDB_DATA kbuf, dbuf;
2841 NT_PRINTER_PARAM *current;
2842 NT_PRINTER_INFO_LEVEL_2 info;
2845 * Delete any printer data 'specifics' already set. When called for driver
2846 * replace, there will generally be some, but during an add printer, there
2847 * should not be any (if there are delete them).
2849 while ( (current=info_ptr->specific) != NULL ) {
2850 info_ptr->specific=current->next;
2851 SAFE_FREE(current->data);
2857 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
2860 kbuf.dsize = strlen(key)+1;
2862 dbuf = tdb_fetch(tdb_drivers, kbuf);
2865 * When changing to a driver that has no init info in the tdb, remove
2866 * the previous drivers init info and leave the new on blank.
2868 free_nt_devicemode(&info_ptr->devmode);
2873 * Get the saved DEVMODE..
2875 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2878 * The saved DEVMODE contains the devicename from the printer used during
2879 * the initialization save. Change it to reflect the new printer.
2881 ZERO_STRUCT(info.devmode->devicename);
2882 fstrcpy(info.devmode->devicename, info_ptr->printername);
2886 * NT/2k does not change out the entire DeviceMode of a printer
2887 * when changing the driver. Only the driverextra, private, &
2888 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
2894 * Bind the saved DEVMODE to the new the printer.
2896 free_nt_devicemode(&info_ptr->devmode);
2897 info_ptr->devmode = info.devmode;
2899 /* copy the entire devmode if we currently don't have one */
2901 if (!info_ptr->devmode) {
2902 DEBUG(10,("set_driver_init_2: Current Devmode is NULL. Copying entire Device Mode\n"));
2903 info_ptr->devmode = info.devmode;
2906 /* only set the necessary fields */
2908 DEBUG(10,("set_driver_init_2: Setting driverversion [0x%x] and private data [0x%x]\n",
2909 info.devmode->driverversion, info.devmode->driverextra));
2911 info_ptr->devmode->driverversion = info.devmode->driverversion;
2913 SAFE_FREE(info_ptr->devmode->private);
2914 info_ptr->devmode->private = NULL;
2916 if (info.devmode->driverversion)
2917 info_ptr->devmode->private = memdup(info.devmode->private, info.devmode->driverversion);
2919 free_nt_devicemode(&info.devmode);
2923 DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
2924 info_ptr->printername, info_ptr->drivername));
2927 * Add the printer data 'specifics' to the new printer
2929 len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len);
2931 SAFE_FREE(dbuf.dptr);
2936 /****************************************************************************
2937 Initialize printer devmode & data with previously saved driver init values.
2938 When a printer is created using AddPrinter, the drivername bound to the
2939 printer is used to lookup previously saved driver initialization info, which
2940 is bound to the new printer.
2941 ****************************************************************************/
2943 uint32 set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
2951 result=set_driver_init_2(printer->info_2);
2962 /****************************************************************************
2963 Pack up the DEVMODE and specifics for a printer into a 'driver init' entry
2964 in the tdb. Note: this is different from the driver entry and the printer
2965 entry. There should be a single driver init entry for each driver regardless
2966 of whether it was installed from NT or 2K. Technically, they should be
2967 different, but they work out to the same struct.
2968 ****************************************************************************/
2970 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
2974 int buflen, len, ret;
2975 TDB_DATA kbuf, dbuf;
2982 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2984 len += pack_specifics(info->specific, buf+len, buflen-len);
2986 if (buflen != len) {
2989 tb = (char *)Realloc(buf, len);
2991 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3000 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3003 kbuf.dsize = strlen(key)+1;
3007 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3011 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3015 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n",
3016 info->sharename, info->drivername));
3021 /****************************************************************************
3022 Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer
3023 ****************************************************************************/
3025 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3029 dump_a_printer(printer, level);
3035 result=update_driver_init_2(printer.info_2);
3046 /****************************************************************************
3047 Convert the printer data value, a REG_BINARY array, into an initialization
3048 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3049 got to keep the endians happy :).
3050 ****************************************************************************/
3052 static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode)
3054 BOOL result = False;
3058 ZERO_STRUCT(devmode);
3060 prs_init(&ps, 0, ctx, UNMARSHALL);
3061 ps.data_p = (char *)param->data;
3062 ps.buffer_size = param->data_len;
3064 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3065 result = convert_devicemode("", &devmode, &nt_devmode);
3067 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3072 /****************************************************************************
3073 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3075 1. Use the driver's config DLL to this UNC printername and:
3076 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3077 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3078 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3080 The last step triggers saving the "driver initialization" information for
3081 this printer into the tdb. Later, new printers that use this driver will
3082 have this initialization information bound to them. This simulates the
3083 driver initialization, as if it had run on the Samba server (as it would
3086 The Win32 client side code requirement sucks! But until we can run arbitrary
3087 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3089 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3090 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3091 about it and you will realize why. JRR 010720
3092 ****************************************************************************/
3094 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
3096 WERROR status = WERR_OK;
3097 TALLOC_CTX *ctx = NULL;
3098 NT_DEVICEMODE *nt_devmode = NULL;
3099 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3102 * When the DEVMODE is already set on the printer, don't try to unpack it.
3105 if (!printer->info_2->devmode && param->data_len) {
3107 * Set devmode on printer info, so entire printer initialization can be
3111 if ((ctx = talloc_init()) == NULL)
3114 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3115 status = WERR_NOMEM;
3119 ZERO_STRUCTP(nt_devmode);
3122 * The DEVMODE is held in the 'data' component of the param in raw binary.
3123 * Convert it to to a devmode structure
3125 if (!convert_driver_init(param, ctx, nt_devmode)) {
3126 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3127 status = WERR_INVALID_PARAM;
3131 printer->info_2->devmode = nt_devmode;
3135 * Pack up and add (or update) the DEVMODE and any current printer data to
3136 * a 'driver init' element in the tdb
3140 if (update_driver_init(*printer, 2)!=0) {
3141 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3142 status = WERR_NOMEM;
3147 * If driver initialization info was successfully saved, set the current
3148 * printer to match it. This allows initialization of the current printer
3149 * as well as the driver.
3151 status = mod_a_printer(*printer, 2);
3152 if (!W_ERROR_IS_OK(status)) {
3153 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3154 printer->info_2->printername));
3158 srv_spoolss_sendnotify(p, handle);
3162 talloc_destroy(ctx);
3164 SAFE_FREE(nt_devmode->private);
3165 SAFE_FREE(nt_devmode);
3166 printer->info_2->devmode = tmp_devmode;
3171 /****************************************************************************
3172 Update the driver init info (DEVMODE and specifics) for a printer
3173 ****************************************************************************/
3175 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
3177 WERROR status = WERR_OK;
3183 status=save_driver_init_2(printer, param);
3187 status=WERR_UNKNOWN_LEVEL;
3194 /****************************************************************************
3195 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3196 ****************************************************************************/
3198 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
3201 NT_PRINTER_INFO_LEVEL *printer = NULL;
3205 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3211 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3212 DEBUG(0,("get_a_printer: malloc fail.\n"));
3215 ZERO_STRUCTP(printer);
3216 result=get_a_printer_2(&printer->info_2, sharename);
3217 if (W_ERROR_IS_OK(result)) {
3218 dump_a_printer(*printer, level);
3219 *pp_printer = printer;
3226 result=WERR_UNKNOWN_LEVEL;
3230 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
3235 /****************************************************************************
3236 Deletes a NT_PRINTER_INFO_LEVEL struct.
3237 ****************************************************************************/
3239 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3242 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3244 DEBUG(104,("freeing a printer at level [%d]\n", level));
3246 if (printer == NULL)
3253 if (printer->info_2 != NULL)
3255 free_nt_printer_info_level_2(&printer->info_2);
3269 SAFE_FREE(*pp_printer);
3273 /****************************************************************************
3274 ****************************************************************************/
3275 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3278 DEBUG(104,("adding a printer at level [%d]\n", level));
3279 dump_a_printer_driver(driver, level);
3285 result=add_a_printer_driver_3(driver.info_3);
3291 result=add_a_printer_driver_6(driver.info_6);
3301 /****************************************************************************
3302 ****************************************************************************/
3303 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3304 fstring printername, fstring architecture, uint32 version)
3312 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
3320 if (W_ERROR_IS_OK(result))
3321 dump_a_printer_driver(*driver, level);
3325 /****************************************************************************
3326 ****************************************************************************/
3327 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3335 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3336 if (driver.info_3 != NULL)
3338 info3=driver.info_3;
3339 SAFE_FREE(info3->dependentfiles);
3340 ZERO_STRUCTP(info3);
3352 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3353 if (driver.info_6 != NULL)
3355 info6=driver.info_6;
3356 SAFE_FREE(info6->dependentfiles);
3357 SAFE_FREE(info6->previousnames);
3358 ZERO_STRUCTP(info6);
3376 /****************************************************************************
3377 Determine whether or not a particular driver is currently assigned
3379 ****************************************************************************/
3380 BOOL printer_driver_in_use (char *arch, char *driver)
3382 TDB_DATA kbuf, newkey, dbuf;
3383 NT_PRINTER_INFO_LEVEL_2 info;
3387 if (!nt_printing_init())
3390 DEBUG(5,("printer_driver_in_use: Beginning search through printers.tdb...\n"));
3392 /* loop through the printers.tdb and check for the drivername */
3393 for (kbuf = tdb_firstkey(tdb_printers); kbuf.dptr;
3394 newkey = tdb_nextkey(tdb_printers, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
3397 dbuf = tdb_fetch(tdb_printers, kbuf);
3401 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) != 0)
3404 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddddddfffffPfffff",
3407 &info.default_priority,
3424 info.printprocessor,
3428 SAFE_FREE(dbuf.dptr);
3431 DEBUG (0,("printer_driver_in_use: tdb_unpack failed for printer %s\n",
3436 DEBUG (10,("printer_driver_in_use: Printer - %s (%s)\n",
3437 info.printername, info.drivername));
3439 if (strcmp(info.drivername, driver) == 0)
3441 DEBUG(5,("printer_driver_in_use: Printer %s using %s\n",
3442 info.printername, driver));
3446 DEBUG(5,("printer_driver_in_use: Completed search through printers.tdb...\n"));
3450 /* report that the driver is in use by default */
3454 /****************************************************************************
3455 Remove a printer driver from the TDB. This assumes that the the driver was
3456 previously looked up.
3457 ***************************************************************************/
3458 WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
3465 get_short_archi(arch, i->environment);
3466 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
3467 arch, i->cversion, i->name);
3468 DEBUG(5,("delete_printer_driver: key = [%s]\n", key));
3471 kbuf.dsize=strlen(key)+1;
3473 if (tdb_delete(tdb_drivers, kbuf) == -1) {
3474 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
3475 return WERR_ACCESS_DENIED;
3478 DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
3483 /****************************************************************************
3484 ****************************************************************************/
3485 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
3486 fstring value, uint8 **data, uint32 *type, uint32 *len)
3488 /* right now that's enough ! */
3489 NT_PRINTER_PARAM *param;
3492 param=printer.info_2->specific;
3494 while (param != NULL && i < param_index) {
3502 /* exited because it exist */
3504 StrnCpy(value, param->value, sizeof(fstring)-1);
3505 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3508 ZERO_STRUCTP(*data);
3509 memcpy(*data, param->data, param->data_len);
3510 *len=param->data_len;
3514 /****************************************************************************
3515 ****************************************************************************/
3516 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
3517 fstring value, uint8 **data, uint32 *type, uint32 *len)
3519 /* right now that's enough ! */
3520 NT_PRINTER_PARAM *param;
3522 DEBUG(10, ("get_specific_param\n"));
3524 param=printer.info_2->specific;
3526 while (param != NULL)
3528 #if 1 /* JRA - I think this should be case insensitive.... */
3529 if ( strequal(value, param->value)
3531 if ( !strcmp(value, param->value)
3533 && strlen(value)==strlen(param->value))
3541 DEBUGADD(10, ("get_specific_param: found one param\n"));
3542 /* exited because it exist */
3545 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3548 memcpy(*data, param->data, param->data_len);
3549 *len=param->data_len;
3551 DEBUGADD(10, ("get_specific_param: exit true\n"));
3554 DEBUGADD(10, ("get_specific_param: exit false\n"));
3558 /****************************************************************************
3559 Store a security desc for a printer.
3560 ****************************************************************************/
3562 WERROR nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
3564 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3565 SEC_DESC_BUF *old_secdesc_ctr = NULL;
3567 TALLOC_CTX *mem_ctx = NULL;
3571 mem_ctx = talloc_init();
3572 if (mem_ctx == NULL)
3575 /* The old owner and group sids of the security descriptor are not
3576 present when new ACEs are added or removed by changing printer
3577 permissions through NT. If they are NULL in the new security
3578 descriptor then copy them over from the old one. */
3580 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3581 DOM_SID *owner_sid, *group_sid;
3582 SEC_ACL *dacl, *sacl;
3583 SEC_DESC *psd = NULL;
3586 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3588 /* Pick out correct owner and group sids */
3590 owner_sid = secdesc_ctr->sec->owner_sid ?
3591 secdesc_ctr->sec->owner_sid :
3592 old_secdesc_ctr->sec->owner_sid;
3594 group_sid = secdesc_ctr->sec->grp_sid ?
3595 secdesc_ctr->sec->grp_sid :
3596 old_secdesc_ctr->sec->grp_sid;
3598 dacl = secdesc_ctr->sec->dacl ?
3599 secdesc_ctr->sec->dacl :
3600 old_secdesc_ctr->sec->dacl;
3602 sacl = secdesc_ctr->sec->sacl ?
3603 secdesc_ctr->sec->sacl :
3604 old_secdesc_ctr->sec->sacl;
3606 /* Make a deep copy of the security descriptor */
3608 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3609 owner_sid, group_sid,
3614 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3617 if (!new_secdesc_ctr) {
3618 new_secdesc_ctr = secdesc_ctr;
3621 /* Store the security descriptor in a tdb */
3623 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3624 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3626 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3628 status = WERR_BADFUNC;
3632 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3634 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
3637 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3638 status = WERR_BADFUNC;
3641 /* Free malloc'ed memory */
3647 talloc_destroy(mem_ctx);
3651 /****************************************************************************
3652 Construct a default security descriptor buffer for a printer.
3653 ****************************************************************************/
3655 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3657 extern DOM_SID global_sam_sid;
3660 SEC_ACL *psa = NULL;
3661 SEC_DESC_BUF *sdb = NULL;
3662 SEC_DESC *psd = NULL;
3666 /* Create an ACE where Everyone is allowed to print */
3668 init_sec_access(&sa, PRINTER_ACE_PRINT);
3669 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3670 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3672 /* Make the security descriptor owned by the Administrators group
3673 on the PDC of the domain. */
3675 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
3676 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3679 /* Backup plan - make printer owned by admins.
3680 This should emulate a lanman printer as security
3681 settings can't be changed. */
3683 sid_copy(&owner_sid, &global_sam_sid);
3684 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3687 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3688 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3689 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
3690 SEC_ACE_FLAG_INHERIT_ONLY);
3692 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3693 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3694 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3696 /* The ACL revision number in rpc_secdesc.h differs from the one
3697 created by NT when setting ACE entries in printer
3698 descriptors. NT4 complains about the property being edited by a
3701 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
3702 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
3704 NULL, psa, &sd_size);
3708 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
3712 sdb = make_sec_desc_buf(ctx, sd_size, psd);
3714 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
3715 (unsigned int)sd_size));
3720 /****************************************************************************
3721 Get a security desc for a printer.
3722 ****************************************************************************/
3724 BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
3730 if ((temp = strchr(printername + 2, '\\'))) {
3731 printername = temp + 1;
3734 /* Fetch security descriptor from tdb */
3736 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3738 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
3739 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
3741 DEBUG(4,("using default secdesc for %s\n", printername));
3743 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
3747 /* Save default security descriptor for later */
3749 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
3750 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
3752 if (sec_io_desc_buf("nt_printing_setsec", secdesc_ctr, &ps, 1))
3753 tdb_prs_store(tdb_printers, key, &ps);
3760 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
3761 this security descriptor has been created when winbindd was
3762 down. Take ownership of security descriptor. */
3764 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
3767 /* Change sd owner to workgroup administrator */
3769 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
3770 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3771 SEC_DESC *psd = NULL;
3776 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3778 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
3780 (*secdesc_ctr)->sec->grp_sid,
3781 (*secdesc_ctr)->sec->sacl,
3782 (*secdesc_ctr)->sec->dacl,
3785 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
3787 /* Swap with other one */
3789 *secdesc_ctr = new_secdesc_ctr;
3793 nt_printing_setsec(printername, *secdesc_ctr);
3797 if (DEBUGLEVEL >= 10) {
3798 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
3801 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3802 printername, the_acl->num_aces));
3804 for (i = 0; i < the_acl->num_aces; i++) {
3807 sid_to_string(sid_str, &the_acl->ace[i].trustee);
3809 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
3810 the_acl->ace[i].type, the_acl->ace[i].flags,
3811 the_acl->ace[i].info.mask));
3821 1: level not implemented
3822 2: file doesn't exist
3823 3: can't allocate memory
3824 4: can't free memory
3825 5: non existant struct
3829 A printer and a printer driver are 2 different things.
3830 NT manages them separatelly, Samba does the same.
3831 Why ? Simply because it's easier and it makes sense !
3833 Now explanation: You have 3 printers behind your samba server,
3834 2 of them are the same make and model (laser A and B). But laser B
3835 has an 3000 sheet feeder and laser A doesn't such an option.
3836 Your third printer is an old dot-matrix model for the accounting :-).
3838 If the /usr/local/samba/lib directory (default dir), you will have
3839 5 files to describe all of this.
3841 3 files for the printers (1 by printer):
3844 NTprinter_accounting
3845 2 files for the drivers (1 for the laser and 1 for the dot matrix)
3846 NTdriver_printer model X
3847 NTdriver_printer model Y
3849 jfm: I should use this comment for the text file to explain
3850 same thing for the forms BTW.
3851 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
3855 /* Convert generic access rights to printer object specific access rights.
3856 It turns out that NT4 security descriptors use generic access rights and
3857 NT5 the object specific ones. */
3859 void map_printer_permissions(SEC_DESC *sd)
3863 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
3864 se_map_generic(&sd->dacl->ace[i].info.mask,
3865 &printer_generic_mapping);
3869 /****************************************************************************
3870 Check a user has permissions to perform the given operation. We use the
3871 permission constants defined in include/rpc_spoolss.h to check the various
3872 actions we perform when checking printer access.
3874 PRINTER_ACCESS_ADMINISTER:
3875 print_queue_pause, print_queue_resume, update_printer_sec,
3876 update_printer, spoolss_addprinterex_level_2,
3877 _spoolss_setprinterdata
3882 JOB_ACCESS_ADMINISTER:
3883 print_job_delete, print_job_pause, print_job_resume,
3886 ****************************************************************************/
3887 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3889 SEC_DESC_BUF *secdesc = NULL;
3890 uint32 access_granted;
3894 TALLOC_CTX *mem_ctx = NULL;
3895 extern struct current_user current_user;
3897 /* If user is NULL then use the current_user structure */
3900 user = ¤t_user;
3902 /* Always allow root or printer admins to do anything */
3904 if (user->uid == 0 ||
3905 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3909 /* Get printer name */
3911 pname = PRINTERNAME(snum);
3913 if (!pname || !*pname) {
3918 /* Get printer security descriptor */
3920 if(!(mem_ctx = talloc_init())) {
3925 nt_printing_getsec(mem_ctx, pname, &secdesc);
3927 if (access_type == JOB_ACCESS_ADMINISTER) {
3928 SEC_DESC_BUF *parent_secdesc = secdesc;
3930 /* Create a child security descriptor to check permissions
3931 against. This is because print jobs are child objects
3932 objects of a printer. */
3934 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
3936 /* Now this is the bit that really confuses me. The access
3937 type needs to be changed from JOB_ACCESS_ADMINISTER to
3938 PRINTER_ACCESS_ADMINISTER for this to work. Something
3939 to do with the child (job) object becoming like a
3942 access_type = PRINTER_ACCESS_ADMINISTER;
3947 map_printer_permissions(secdesc->sec);
3949 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
3950 &access_granted, &status);
3952 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3954 talloc_destroy(mem_ctx);
3962 /****************************************************************************
3963 Check the time parameters allow a print operation.
3964 *****************************************************************************/
3966 BOOL print_time_access_check(int snum)
3968 NT_PRINTER_INFO_LEVEL *printer = NULL;
3970 time_t now = time(NULL);
3974 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3977 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3981 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3983 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3986 free_a_printer(&printer, 2);
3994 #if 0 /* JERRY - not used */
3995 /****************************************************************************
3996 Attempt to write a default device.
3997 *****************************************************************************/
3999 WERROR printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
4001 NT_PRINTER_INFO_LEVEL *printer = NULL;
4005 * Don't bother if no default devicemode was sent.
4008 if (printer_default->devmode_cont.devmode == NULL)
4011 result = get_a_printer(&printer, 2, lp_servicename(snum));
4012 if (!W_ERROR_IS_OK(result)) return result;
4015 * Just ignore it if we already have a devmode.
4018 if (printer->info_2->devmode != NULL)
4022 * We don't have a devicemode and we're trying to write
4023 * one. Check we have the access needed.
4025 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
4027 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
4028 PRINTER_ACCESS_ADMINISTER) {
4029 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
4030 result = WERR_ACCESS_DENIED;
4034 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4035 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
4036 lp_servicename(snum) ));
4037 result = WERR_ACCESS_DENIED;
4038 /*result = NT_STATUS_NO_PROBLEMO;*/
4042 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
4045 * Convert the on the wire devicemode format to the internal one.
4048 if (!convert_devicemode(printer->info_2->printername,
4049 printer_default->devmode_cont.devmode,
4050 &printer->info_2->devmode)) {
4051 result = WERR_NOMEM;
4056 * Finally write back to the tdb.
4059 result = mod_a_printer(*printer, 2);
4063 free_a_printer(&printer, 2);