2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
6 * Copyright (C) Gerald Carter 2002.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 extern DOM_SID global_sid_World
;
27 static TDB_CONTEXT
*tdb_forms
; /* used for forms files */
28 static TDB_CONTEXT
*tdb_drivers
; /* used for driver files */
29 static TDB_CONTEXT
*tdb_printers
; /* used for printers files */
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
42 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
44 /* Map generic permissions to printer object specific permissions */
46 GENERIC_MAPPING printer_generic_mapping
= {
53 STANDARD_MAPPING printer_std_mapping
= {
60 /* Map generic permissions to print server object specific permissions */
62 GENERIC_MAPPING printserver_generic_mapping
= {
69 STANDARD_MAPPING printserver_std_mapping
= {
76 /* We need one default form to support our default printer. Msoft adds the
77 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
78 array index). Letter is always first, so (for the current code) additions
79 always put things in the correct order. */
80 static nt_forms_struct default_forms
[] = {
81 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
84 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
85 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
86 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
87 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
88 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
89 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
92 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
93 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
94 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
95 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
96 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
97 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
98 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
99 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
100 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
101 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
102 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
103 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
104 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
105 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
106 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
107 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
108 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
109 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
110 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
111 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
112 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
113 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
114 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
115 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
116 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
117 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
118 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
119 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
120 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
121 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
122 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
123 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
124 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
125 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
126 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
127 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
128 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
131 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
132 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
133 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
134 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
135 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
136 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
138 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
139 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
140 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
141 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
142 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
143 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
144 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
145 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
146 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
147 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
148 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
149 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
150 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
151 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
152 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
153 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
154 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
155 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
156 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
157 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
158 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
159 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
160 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
161 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
162 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
163 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
164 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
165 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
166 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
167 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
168 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
169 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
170 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
171 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
172 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
173 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
174 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
175 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
176 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
177 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
178 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
179 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
180 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
181 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
182 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
183 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
184 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
185 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
186 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
187 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
188 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
189 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
190 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
191 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
192 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
193 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
194 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
195 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
196 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
197 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
198 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
201 static BOOL
upgrade_to_version_3(void)
203 TDB_DATA kbuf
, newkey
, dbuf
;
205 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
207 for (kbuf
= tdb_firstkey(tdb_drivers
); kbuf
.dptr
;
208 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
210 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
212 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) == 0) {
213 DEBUG(0,("upgrade_to_version_3:moving form\n"));
214 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
215 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms
)));
218 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
219 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
224 if (strncmp(kbuf
.dptr
, PRINTERS_PREFIX
, strlen(PRINTERS_PREFIX
)) == 0) {
225 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
226 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
227 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers
)));
230 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
231 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
236 if (strncmp(kbuf
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
)) == 0) {
237 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
238 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
239 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers
)));
242 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
243 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
248 SAFE_FREE(dbuf
.dptr
);
254 /****************************************************************************
255 Open the NT printing tdb.
256 ****************************************************************************/
258 BOOL
nt_printing_init(void)
260 static pid_t local_pid
;
261 char *vstring
= "INFO/version";
263 if (tdb_drivers
&& tdb_printers
&& tdb_forms
&& local_pid
== sys_getpid())
266 tdb_drivers
= tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
268 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
269 lock_path("ntdrivers.tdb"), strerror(errno
) ));
273 tdb_printers
= tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
275 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
276 lock_path("ntprinters.tdb"), strerror(errno
) ));
280 tdb_forms
= tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
282 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
283 lock_path("ntforms.tdb"), strerror(errno
) ));
287 local_pid
= sys_getpid();
289 /* handle a Samba upgrade */
290 tdb_lock_bystring(tdb_drivers
, vstring
);
294 /* Cope with byte-reversed older versions of the db. */
295 vers_id
= tdb_fetch_int32(tdb_drivers
, vstring
);
296 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_2
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_2
)) {
297 /* Written on a bigendian machine with old fetch_int code. Save as le. */
298 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
299 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION
);
300 vers_id
= NTDRIVERS_DATABASE_VERSION
;
303 if (vers_id
!= NTDRIVERS_DATABASE_VERSION
) {
305 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_1
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_1
)) {
306 if (!upgrade_to_version_3())
309 tdb_traverse(tdb_drivers
, tdb_traverse_delete_fn
, NULL
);
311 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION
);
314 tdb_unlock_bystring(tdb_drivers
, vstring
);
316 update_c_setprinter(True
);
319 * register callback to handle updating printers as new
320 * drivers are installed
323 message_register( MSG_PRINTER_DRVUPGRADE
, do_drv_upgrade_printer
);
326 * register callback to handle updating printer data
327 * when a driver is initialized
330 message_register( MSG_PRINTERDATA_INIT_RESET
, reset_all_printerdata
);
336 /*******************************************************************
337 tdb traversal function for counting printers.
338 ********************************************************************/
340 static int traverse_counting_printers(TDB_CONTEXT
*t
, TDB_DATA key
,
341 TDB_DATA data
, void *context
)
343 int *printer_count
= (int*)context
;
345 if (memcmp(PRINTERS_PREFIX
, key
.dptr
, sizeof(PRINTERS_PREFIX
)-1) == 0) {
347 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key
.dptr
, *printer_count
));
353 /*******************************************************************
354 Update the spooler global c_setprinter. This variable is initialized
355 when the parent smbd starts with the number of existing printers. It
356 is monotonically increased by the current number of printers *after*
357 each add or delete printer RPC. Only Microsoft knows why... JRR020119
358 ********************************************************************/
360 uint32
update_c_setprinter(BOOL initialize
)
363 int32 printer_count
= 0;
365 tdb_lock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
367 /* Traverse the tdb, counting the printers */
368 tdb_traverse(tdb_printers
, traverse_counting_printers
, (void *)&printer_count
);
370 /* If initializing, set c_setprinter to current printers count
371 * otherwise, bump it by the current printer count
374 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
) + printer_count
;
376 c_setprinter
= printer_count
;
378 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter
));
379 tdb_store_int32(tdb_printers
, GLOBAL_C_SETPRINTER
, c_setprinter
);
381 tdb_unlock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
383 return (uint32
)c_setprinter
;
386 /*******************************************************************
387 Get the spooler global c_setprinter, accounting for initialization.
388 ********************************************************************/
390 uint32
get_c_setprinter(void)
392 int32 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
);
394 if (c_setprinter
== (int32
)-1)
395 c_setprinter
= update_c_setprinter(True
);
397 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter
));
399 return (uint32
)c_setprinter
;
402 /****************************************************************************
403 Get builtin form struct list.
404 ****************************************************************************/
406 int get_builtin_ntforms(nt_forms_struct
**list
)
408 *list
= (nt_forms_struct
*)memdup(&default_forms
[0], sizeof(default_forms
));
409 return sizeof(default_forms
) / sizeof(default_forms
[0]);
412 /****************************************************************************
413 get a builtin form struct
414 ****************************************************************************/
416 BOOL
get_a_builtin_ntform(UNISTR2
*uni_formname
,nt_forms_struct
*form
)
420 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
421 DEBUGADD(6,("Looking for builtin form %s \n", form_name
));
422 count
= sizeof(default_forms
) / sizeof(default_forms
[0]);
423 for (i
=0;i
<count
;i
++) {
424 if (strequal(form_name
,default_forms
[i
].name
)) {
425 DEBUGADD(6,("Found builtin form %s \n", form_name
));
426 memcpy(form
,&default_forms
[i
],sizeof(*form
));
434 /****************************************************************************
435 get a form struct list
436 ****************************************************************************/
437 int get_ntforms(nt_forms_struct
**list
)
439 TDB_DATA kbuf
, newkey
, dbuf
;
441 nt_forms_struct form
;
446 for (kbuf
= tdb_firstkey(tdb_forms
);
448 newkey
= tdb_nextkey(tdb_forms
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
)
450 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) != 0)
453 dbuf
= tdb_fetch(tdb_forms
, kbuf
);
457 fstrcpy(form
.name
, kbuf
.dptr
+strlen(FORMS_PREFIX
));
458 ret
= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dddddddd",
459 &i
, &form
.flag
, &form
.width
, &form
.length
, &form
.left
,
460 &form
.top
, &form
.right
, &form
.bottom
);
461 SAFE_FREE(dbuf
.dptr
);
462 if (ret
!= dbuf
.dsize
)
465 tl
= Realloc(*list
, sizeof(nt_forms_struct
)*(n
+1));
467 DEBUG(0,("get_ntforms: Realloc fail.\n"));
479 /****************************************************************************
480 write a form struct list
481 ****************************************************************************/
482 int write_ntforms(nt_forms_struct
**list
, int number
)
489 for (i
=0;i
<number
;i
++) {
490 /* save index, so list is rebuilt in correct order */
491 len
= tdb_pack(buf
, sizeof(buf
), "dddddddd",
492 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
493 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
495 if (len
> sizeof(buf
)) break;
496 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[i
].name
);
497 kbuf
.dsize
= strlen(key
)+1;
501 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) break;
507 /****************************************************************************
508 add a form struct at the end of the list
509 ****************************************************************************/
510 BOOL
add_a_form(nt_forms_struct
**list
, const FORM
*form
, int *count
)
518 * NT tries to add forms even when
519 * they are already in the base
520 * only update the values if already present
525 unistr2_to_ascii(form_name
, &form
->name
, sizeof(form_name
)-1);
526 for (n
=0; n
<*count
; n
++) {
527 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
528 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name
));
535 if((tl
=Realloc(*list
, (n
+1)*sizeof(nt_forms_struct
))) == NULL
) {
536 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
540 unistr2_to_ascii((*list
)[n
].name
, &form
->name
, sizeof((*list
)[n
].name
)-1);
544 (*list
)[n
].flag
=form
->flags
;
545 (*list
)[n
].width
=form
->size_x
;
546 (*list
)[n
].length
=form
->size_y
;
547 (*list
)[n
].left
=form
->left
;
548 (*list
)[n
].top
=form
->top
;
549 (*list
)[n
].right
=form
->right
;
550 (*list
)[n
].bottom
=form
->bottom
;
555 /****************************************************************************
556 delete a named form struct
557 ****************************************************************************/
558 BOOL
delete_a_form(nt_forms_struct
**list
, UNISTR2
*del_name
, int *count
, WERROR
*ret
)
567 unistr2_to_ascii(form_name
, del_name
, sizeof(form_name
)-1);
569 for (n
=0; n
<*count
; n
++) {
570 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
571 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name
));
577 DEBUG(10,("delete_a_form, [%s] not found\n", form_name
));
578 *ret
= WERR_INVALID_PARAM
;
582 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[n
].name
);
583 kbuf
.dsize
= strlen(key
)+1;
585 if (tdb_delete(tdb_forms
, kbuf
) != 0) {
593 /****************************************************************************
595 ****************************************************************************/
596 void update_a_form(nt_forms_struct
**list
, const FORM
*form
, int count
)
600 unistr2_to_ascii(form_name
, &(form
->name
), sizeof(form_name
)-1);
602 DEBUG(106, ("[%s]\n", form_name
));
603 for (n
=0; n
<count
; n
++)
605 DEBUGADD(106, ("n [%d]:[%s]\n", n
, (*list
)[n
].name
));
606 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
)))
610 if (n
==count
) return;
612 (*list
)[n
].flag
=form
->flags
;
613 (*list
)[n
].width
=form
->size_x
;
614 (*list
)[n
].length
=form
->size_y
;
615 (*list
)[n
].left
=form
->left
;
616 (*list
)[n
].top
=form
->top
;
617 (*list
)[n
].right
=form
->right
;
618 (*list
)[n
].bottom
=form
->bottom
;
621 /****************************************************************************
622 get the nt drivers list
624 traverse the database and look-up the matching names
625 ****************************************************************************/
626 int get_ntdrivers(fstring
**list
, char *architecture
, uint32 version
)
632 TDB_DATA kbuf
, newkey
;
634 get_short_archi(short_archi
, architecture
);
635 slprintf(key
, sizeof(key
)-1, "%s%s/%d/", DRIVERS_PREFIX
, short_archi
, version
);
637 for (kbuf
= tdb_firstkey(tdb_drivers
);
639 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
640 if (strncmp(kbuf
.dptr
, key
, strlen(key
)) != 0) continue;
642 if((fl
= Realloc(*list
, sizeof(fstring
)*(total
+1))) == NULL
) {
643 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
648 fstrcpy((*list
)[total
], kbuf
.dptr
+strlen(key
));
655 /****************************************************************************
656 function to do the mapping between the long architecture name and
658 ****************************************************************************/
659 BOOL
get_short_archi(char *short_archi
, char *long_archi
)
666 struct table archi_table
[]=
668 {"Windows 4.0", "WIN40" },
669 {"Windows NT x86", "W32X86" },
670 {"Windows NT R4000", "W32MIPS" },
671 {"Windows NT Alpha_AXP", "W32ALPHA" },
672 {"Windows NT PowerPC", "W32PPC" },
678 DEBUG(107,("Getting architecture dependant directory\n"));
681 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
682 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
684 if (archi_table
[i
].long_archi
==NULL
) {
685 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi
));
689 StrnCpy (short_archi
, archi_table
[i
].short_archi
, strlen(archi_table
[i
].short_archi
));
691 DEBUGADD(108,("index: [%d]\n", i
));
692 DEBUGADD(108,("long architecture: [%s]\n", long_archi
));
693 DEBUGADD(108,("short architecture: [%s]\n", short_archi
));
698 /****************************************************************************
699 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
700 There are two case to be covered here: PE (Portable Executable) and NE (New
701 Executable) files. Both files support the same INFO structure, but PE files
702 store the signature in unicode, and NE files store it as !unicode.
703 returns -1 on error, 1 on version info found, and 0 on no version info found.
704 ****************************************************************************/
706 static int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
712 if ((buf
=malloc(PE_HEADER_SIZE
)) == NULL
) {
713 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
714 fname
, PE_HEADER_SIZE
));
718 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
719 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
720 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
722 goto no_version_info
;
725 /* Is this really a DOS header? */
726 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
727 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
728 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
729 goto no_version_info
;
732 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
733 if (fsp
->conn
->vfs_ops
.lseek(fsp
, fsp
->fd
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
734 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
736 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
737 goto no_version_info
;
740 if ((byte_count
= vfs_read_data(fsp
, buf
, PE_HEADER_SIZE
)) < PE_HEADER_SIZE
) {
741 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
743 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
744 goto no_version_info
;
747 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
748 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
750 int section_table_bytes
;
752 if (SVAL(buf
,PE_HEADER_MACHINE_OFFSET
) != PE_HEADER_MACHINE_I386
) {
753 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
754 fname
, SVAL(buf
,PE_HEADER_MACHINE_OFFSET
)));
755 /* At this point, we assume the file is in error. It still could be somthing
756 * else besides a PE file, but it unlikely at this point.
761 /* get the section table */
762 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
763 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
765 if ((buf
=malloc(section_table_bytes
)) == NULL
) {
766 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
767 fname
, section_table_bytes
));
771 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
772 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
777 /* Iterate the section table looking for the resource section ".rsrc" */
778 for (i
= 0; i
< num_sections
; i
++) {
779 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
781 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
782 int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
783 int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
786 if ((buf
=malloc(section_bytes
)) == NULL
) {
787 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
788 fname
, section_bytes
));
792 /* Seek to the start of the .rsrc section info */
793 if (fsp
->conn
->vfs_ops
.lseek(fsp
, fsp
->fd
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
794 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
799 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
800 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
805 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
806 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
807 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
808 /* Align to next long address */
809 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
811 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
812 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
813 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
815 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
816 fname
, *major
, *minor
,
817 (*major
>>16)&0xffff, *major
&0xffff,
818 (*minor
>>16)&0xffff, *minor
&0xffff));
827 /* Version info not found, fall back to origin date/time */
828 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
832 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
833 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
834 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
835 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
836 /* At this point, we assume the file is in error. It still could be somthing
837 * else besides a NE file, but it unlikely at this point. */
841 /* Allocate a bit more space to speed up things */
843 if ((buf
=malloc(VS_NE_BUF_SIZE
)) == NULL
) {
844 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
845 fname
, PE_HEADER_SIZE
));
849 /* This is a HACK! I got tired of trying to sort through the messy
850 * 'NE' file format. If anyone wants to clean this up please have at
851 * it, but this works. 'NE' files will eventually fade away. JRR */
852 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
853 /* Cover case that should not occur in a well formed 'NE' .dll file */
854 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
856 for(i
=0; i
<byte_count
; i
++) {
857 /* Fast skip past data that can't possibly match */
858 if (buf
[i
] != 'V') continue;
860 /* Potential match data crosses buf boundry, move it to beginning
861 * of buf, and fill the buf with as much as it will hold. */
862 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
865 memcpy(buf
, &buf
[i
], byte_count
-i
);
866 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
867 (byte_count
-i
))) < 0) {
869 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
874 byte_count
= bc
+ (byte_count
- i
);
875 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
880 /* Check that the full signature string and the magic number that
881 * follows exist (not a perfect solution, but the chances that this
882 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
883 * twice, as it is simpler to read the code. */
884 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
885 /* Compute skip alignment to next long address */
886 int skip
= -(fsp
->conn
->vfs_ops
.lseek(fsp
, fsp
->fd
, 0, SEEK_CUR
) - (byte_count
- i
) +
887 sizeof(VS_SIGNATURE
)) & 3;
888 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
890 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
891 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
892 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
893 fname
, *major
, *minor
,
894 (*major
>>16)&0xffff, *major
&0xffff,
895 (*minor
>>16)&0xffff, *minor
&0xffff));
902 /* Version info not found, fall back to origin date/time */
903 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
908 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
909 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
910 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
921 /****************************************************************************
922 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
923 share one or more files. During the MS installation process files are checked
924 to insure that only a newer version of a shared file is installed over an
925 older version. There are several possibilities for this comparison. If there
926 is no previous version, the new one is newer (obviously). If either file is
927 missing the version info structure, compare the creation date (on Unix use
928 the modification date). Otherwise chose the numerically larger version number.
929 ****************************************************************************/
930 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
,
933 BOOL use_version
= True
;
938 time_t new_create_time
;
942 time_t old_create_time
;
946 files_struct
*fsp
= NULL
;
948 SMB_STRUCT_STAT stat_buf
;
952 ZERO_STRUCT(stat_buf
);
953 new_create_time
= (time_t)0;
954 old_create_time
= (time_t)0;
956 /* Get file version info (if available) for previous file (if it exists) */
957 pstrcpy(filepath
, old_file
);
959 unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
961 fsp
= open_file_shared(conn
, filepath
, &stat_buf
,
962 SET_OPEN_MODE(DOS_OPEN_RDONLY
),
963 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
964 0, 0, &access_mode
, &action
);
966 /* Old file not found, so by definition new file is in fact newer */
967 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
972 int ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
973 if (ret
== -1) goto error_exit
;
976 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
979 if (fsp
->conn
->vfs_ops
.fstat(fsp
, fsp
->fd
, &st
) == -1) goto error_exit
;
980 old_create_time
= st
.st_mtime
;
981 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time
));
984 close_file(fsp
, True
);
986 /* Get file version info (if available) for new file */
987 pstrcpy(filepath
, new_file
);
988 unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
990 fsp
= open_file_shared(conn
, filepath
, &stat_buf
,
991 SET_OPEN_MODE(DOS_OPEN_RDONLY
),
992 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
993 0, 0, &access_mode
, &action
);
995 /* New file not found, this shouldn't occur if the caller did its job */
996 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1001 int ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
1002 if (ret
== -1) goto error_exit
;
1005 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1007 use_version
= False
;
1008 if (fsp
->conn
->vfs_ops
.fstat(fsp
, fsp
->fd
, &st
) == -1) goto error_exit
;
1009 new_create_time
= st
.st_mtime
;
1010 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time
));
1013 close_file(fsp
, True
);
1015 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
1016 /* Compare versions and choose the larger version number */
1017 if (new_major
> old_major
||
1018 (new_major
== old_major
&& new_minor
> old_minor
)) {
1020 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1024 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1029 /* Compare modification time/dates and choose the newest time/date */
1030 if (new_create_time
> old_create_time
) {
1031 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1035 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1042 close_file(fsp
, True
);
1046 /****************************************************************************
1047 Determine the correct cVersion associated with an architecture and driver
1048 ****************************************************************************/
1049 static uint32
get_correct_cversion(fstring architecture
, fstring driverpath_in
,
1050 struct current_user
*user
, WERROR
*perr
)
1058 files_struct
*fsp
= NULL
;
1061 connection_struct
*conn
;
1065 *perr
= WERR_INVALID_PARAM
;
1067 /* If architecture is Windows 95/98/ME, the version is always 0. */
1068 if (strcmp(architecture
, "WIN40") == 0) {
1069 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1075 * Connect to the print$ share under the same account as the user connected
1076 * to the rpc pipe. Note we must still be root to do this.
1079 /* Null password is ok - we are already an authenticated user... */
1080 null_pw
= data_blob(NULL
, 0);
1082 conn
= make_connection_with_chdir("print$", null_pw
, "A:", user
->vuid
, &nt_status
);
1086 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1087 *perr
= ntstatus_to_werror(nt_status
);
1091 /* We are temporarily becoming the connection user. */
1092 if (!become_user(conn
, conn
->vuid
)) {
1093 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1094 *perr
= WERR_ACCESS_DENIED
;
1098 /* Open the driver file (Portable Executable format) and determine the
1099 * deriver the cversion. */
1100 slprintf(driverpath
, sizeof(driverpath
)-1, "%s/%s", architecture
, driverpath_in
);
1102 unix_convert(driverpath
,conn
,NULL
,&bad_path
,&st
);
1104 fsp
= open_file_shared(conn
, driverpath
, &st
,
1105 SET_OPEN_MODE(DOS_OPEN_RDONLY
),
1106 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1107 0, 0, &access_mode
, &action
);
1109 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1110 driverpath
, errno
));
1111 *perr
= WERR_ACCESS_DENIED
;
1117 int ret
= get_file_version(fsp
, driverpath
, &major
, &minor
);
1118 if (ret
== -1) goto error_exit
;
1121 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath
));
1126 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1127 * for more details. Version in this case is not just the version of the
1128 * file, but the version in the sense of kernal mode (2) vs. user mode
1129 * (3) drivers. Other bits of the version fields are the version info.
1132 cversion
= major
& 0x0000ffff;
1134 case 2: /* WinNT drivers */
1135 case 3: /* Win2K drivers */
1139 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1140 driverpath
, cversion
));
1144 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1145 driverpath
, major
, minor
));
1148 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1149 driverpath
, cversion
));
1151 close_file(fsp
, True
);
1152 close_cnum(conn
, user
->vuid
);
1161 close_file(fsp
, True
);
1163 close_cnum(conn
, user
->vuid
);
1168 /****************************************************************************
1169 ****************************************************************************/
1170 static WERROR
clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
,
1171 struct current_user
*user
)
1173 fstring architecture
;
1179 /* clean up the driver name.
1180 * we can get .\driver.dll
1181 * or worse c:\windows\system\driver.dll !
1183 /* using an intermediate string to not have overlaping memcpy()'s */
1184 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1185 fstrcpy(new_name
, p
+1);
1186 fstrcpy(driver
->driverpath
, new_name
);
1189 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1190 fstrcpy(new_name
, p
+1);
1191 fstrcpy(driver
->datafile
, new_name
);
1194 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1195 fstrcpy(new_name
, p
+1);
1196 fstrcpy(driver
->configfile
, new_name
);
1199 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1200 fstrcpy(new_name
, p
+1);
1201 fstrcpy(driver
->helpfile
, new_name
);
1204 if (driver
->dependentfiles
) {
1205 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1206 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1207 fstrcpy(new_name
, p
+1);
1208 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1213 get_short_archi(architecture
, driver
->environment
);
1215 /* jfm:7/16/2000 the client always sends the cversion=0.
1216 * The server should check which version the driver is by reading
1217 * the PE header of driver->driverpath.
1219 * For Windows 95/98 the version is 0 (so the value sent is correct)
1220 * For Windows NT (the architecture doesn't matter)
1221 * NT 3.1: cversion=0
1222 * NT 3.5/3.51: cversion=1
1226 if ((driver
->cversion
= get_correct_cversion( architecture
,
1227 driver
->driverpath
, user
, &err
)) == -1)
1233 /****************************************************************************
1234 ****************************************************************************/
1235 static WERROR
clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
, struct current_user
*user
)
1237 fstring architecture
;
1243 /* clean up the driver name.
1244 * we can get .\driver.dll
1245 * or worse c:\windows\system\driver.dll !
1247 /* using an intermediate string to not have overlaping memcpy()'s */
1248 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1249 fstrcpy(new_name
, p
+1);
1250 fstrcpy(driver
->driverpath
, new_name
);
1253 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1254 fstrcpy(new_name
, p
+1);
1255 fstrcpy(driver
->datafile
, new_name
);
1258 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1259 fstrcpy(new_name
, p
+1);
1260 fstrcpy(driver
->configfile
, new_name
);
1263 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1264 fstrcpy(new_name
, p
+1);
1265 fstrcpy(driver
->helpfile
, new_name
);
1268 if (driver
->dependentfiles
) {
1269 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1270 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1271 fstrcpy(new_name
, p
+1);
1272 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1277 get_short_archi(architecture
, driver
->environment
);
1279 /* jfm:7/16/2000 the client always sends the cversion=0.
1280 * The server should check which version the driver is by reading
1281 * the PE header of driver->driverpath.
1283 * For Windows 95/98 the version is 0 (so the value sent is correct)
1284 * For Windows NT (the architecture doesn't matter)
1285 * NT 3.1: cversion=0
1286 * NT 3.5/3.51: cversion=1
1290 if ((driver
->version
= get_correct_cversion(architecture
, driver
->driverpath
, user
, &err
)) == -1)
1296 /****************************************************************************
1297 ****************************************************************************/
1298 WERROR
clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
,
1299 uint32 level
, struct current_user
*user
)
1304 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1305 driver
=driver_abstract
.info_3
;
1306 return clean_up_driver_struct_level_3(driver
, user
);
1310 NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
;
1311 driver
=driver_abstract
.info_6
;
1312 return clean_up_driver_struct_level_6(driver
, user
);
1315 return WERR_INVALID_PARAM
;
1319 /****************************************************************************
1320 This function sucks and should be replaced. JRA.
1321 ****************************************************************************/
1323 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*dst
, NT_PRINTER_DRIVER_INFO_LEVEL_6
*src
)
1325 dst
->cversion
= src
->version
;
1327 fstrcpy( dst
->name
, src
->name
);
1328 fstrcpy( dst
->environment
, src
->environment
);
1329 fstrcpy( dst
->driverpath
, src
->driverpath
);
1330 fstrcpy( dst
->datafile
, src
->datafile
);
1331 fstrcpy( dst
->configfile
, src
->configfile
);
1332 fstrcpy( dst
->helpfile
, src
->helpfile
);
1333 fstrcpy( dst
->monitorname
, src
->monitorname
);
1334 fstrcpy( dst
->defaultdatatype
, src
->defaultdatatype
);
1335 dst
->dependentfiles
= src
->dependentfiles
;
1338 #if 0 /* Debugging function */
1340 static char* ffmt(unsigned char *c
){
1342 static char ffmt_str
[17];
1344 for (i
=0; i
<16; i
++) {
1345 if ((c
[i
] < ' ') || (c
[i
] > '~'))
1356 /****************************************************************************
1357 ****************************************************************************/
1358 BOOL
move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
, uint32 level
,
1359 struct current_user
*user
, WERROR
*perr
)
1361 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1362 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver
;
1363 fstring architecture
;
1368 connection_struct
*conn
;
1375 memset(inbuf
, '\0', sizeof(inbuf
));
1376 memset(outbuf
, '\0', sizeof(outbuf
));
1380 driver
=driver_abstract
.info_3
;
1381 else if (level
==6) {
1382 convert_level_6_to_level3(&converted_driver
, driver_abstract
.info_6
);
1383 driver
= &converted_driver
;
1385 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level
));
1389 get_short_archi(architecture
, driver
->environment
);
1392 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1393 * Note we must be root to do this.
1397 null_pw
= data_blob(NULL
, 0);
1398 conn
= make_connection_with_chdir("print$", null_pw
, "A:", user
->vuid
, &nt_status
);
1402 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1403 *perr
= ntstatus_to_werror(nt_status
);
1408 * Save who we are - we are temporarily becoming the connection user.
1411 if (!become_user(conn
, conn
->vuid
)) {
1412 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1417 * make the directories version and version\driver_name
1418 * under the architecture directory.
1420 DEBUG(5,("Creating first directory\n"));
1421 slprintf(new_dir
, sizeof(new_dir
)-1, "%s/%d", architecture
, driver
->cversion
);
1422 mkdir_internal(conn
, new_dir
);
1424 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1425 * listed for this driver which has already been moved, skip it (note:
1426 * drivers may list the same file name several times. Then check if the
1427 * file already exists in archi\cversion\, if so, check that the version
1428 * info (or time stamps if version info is unavailable) is newer (or the
1429 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1430 * Otherwise, delete the file.
1432 * If a file is not moved to archi\cversion\ because of an error, all the
1433 * rest of the 'unmoved' driver files are removed from archi\. If one or
1434 * more of the driver's files was already moved to archi\cversion\, it
1435 * potentially leaves the driver in a partially updated state. Version
1436 * trauma will most likely occur if an client attempts to use any printer
1437 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1438 * done is appropriate... later JRR
1441 DEBUG(5,("Moving files now !\n"));
1443 if (driver
->driverpath
&& strlen(driver
->driverpath
)) {
1444 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->driverpath
);
1445 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->driverpath
);
1446 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1448 status
= rename_internals(conn
, new_name
, old_name
, True
);
1449 if (!NT_STATUS_IS_OK(status
)) {
1450 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1451 new_name
, old_name
));
1452 *perr
= ntstatus_to_werror(status
);
1453 unlink_internals(conn
, 0, new_name
);
1458 unlink_internals(conn
, 0, new_name
);
1461 if (driver
->datafile
&& strlen(driver
->datafile
)) {
1462 if (!strequal(driver
->datafile
, driver
->driverpath
)) {
1463 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->datafile
);
1464 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->datafile
);
1465 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1467 status
= rename_internals(conn
, new_name
, old_name
, True
);
1468 if (!NT_STATUS_IS_OK(status
)) {
1469 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1470 new_name
, old_name
));
1471 *perr
= ntstatus_to_werror(status
);
1472 unlink_internals(conn
, 0, new_name
);
1477 unlink_internals(conn
, 0, new_name
);
1481 if (driver
->configfile
&& strlen(driver
->configfile
)) {
1482 if (!strequal(driver
->configfile
, driver
->driverpath
) &&
1483 !strequal(driver
->configfile
, driver
->datafile
)) {
1484 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->configfile
);
1485 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->configfile
);
1486 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1488 status
= rename_internals(conn
, new_name
, old_name
, True
);
1489 if (!NT_STATUS_IS_OK(status
)) {
1490 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1491 new_name
, old_name
));
1492 *perr
= ntstatus_to_werror(status
);
1493 unlink_internals(conn
, 0, new_name
);
1498 unlink_internals(conn
, 0, new_name
);
1502 if (driver
->helpfile
&& strlen(driver
->helpfile
)) {
1503 if (!strequal(driver
->helpfile
, driver
->driverpath
) &&
1504 !strequal(driver
->helpfile
, driver
->datafile
) &&
1505 !strequal(driver
->helpfile
, driver
->configfile
)) {
1506 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->helpfile
);
1507 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->helpfile
);
1508 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1510 status
= rename_internals(conn
, new_name
, old_name
, True
);
1511 if (!NT_STATUS_IS_OK(status
)) {
1512 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1513 new_name
, old_name
));
1514 *perr
= ntstatus_to_werror(status
);
1515 unlink_internals(conn
, 0, new_name
);
1520 unlink_internals(conn
, 0, new_name
);
1524 if (driver
->dependentfiles
) {
1525 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1526 if (!strequal(driver
->dependentfiles
[i
], driver
->driverpath
) &&
1527 !strequal(driver
->dependentfiles
[i
], driver
->datafile
) &&
1528 !strequal(driver
->dependentfiles
[i
], driver
->configfile
) &&
1529 !strequal(driver
->dependentfiles
[i
], driver
->helpfile
)) {
1531 for (j
=0; j
< i
; j
++) {
1532 if (strequal(driver
->dependentfiles
[i
], driver
->dependentfiles
[j
])) {
1537 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->dependentfiles
[i
]);
1538 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->dependentfiles
[i
]);
1539 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1541 status
= rename_internals(conn
, new_name
, old_name
, True
);
1542 if (!NT_STATUS_IS_OK(status
)) {
1543 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1544 new_name
, old_name
));
1545 *perr
= ntstatus_to_werror(status
);
1546 unlink_internals(conn
, 0, new_name
);
1551 unlink_internals(conn
, 0, new_name
);
1557 close_cnum(conn
, user
->vuid
);
1560 return ver
== -1 ? False
: True
;
1563 /****************************************************************************
1564 ****************************************************************************/
1565 static uint32
add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
)
1568 fstring architecture
;
1574 TDB_DATA kbuf
, dbuf
;
1576 get_short_archi(architecture
, driver
->environment
);
1578 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1579 * \\server is added in the rpc server layer.
1580 * It does make sense to NOT store the server's name in the printer TDB.
1583 slprintf(directory
, sizeof(directory
)-1, "\\print$\\%s\\%d\\", architecture
, driver
->cversion
);
1585 /* .inf files do not always list a file for each of the four standard files.
1586 * Don't prepend a path to a null filename, or client claims:
1587 * "The server on which the printer resides does not have a suitable
1588 * <printer driver name> printer driver installed. Click OK if you
1589 * wish to install the driver on your local machine."
1591 if (strlen(driver
->driverpath
)) {
1592 fstrcpy(temp_name
, driver
->driverpath
);
1593 slprintf(driver
->driverpath
, sizeof(driver
->driverpath
)-1, "%s%s", directory
, temp_name
);
1596 if (strlen(driver
->datafile
)) {
1597 fstrcpy(temp_name
, driver
->datafile
);
1598 slprintf(driver
->datafile
, sizeof(driver
->datafile
)-1, "%s%s", directory
, temp_name
);
1601 if (strlen(driver
->configfile
)) {
1602 fstrcpy(temp_name
, driver
->configfile
);
1603 slprintf(driver
->configfile
, sizeof(driver
->configfile
)-1, "%s%s", directory
, temp_name
);
1606 if (strlen(driver
->helpfile
)) {
1607 fstrcpy(temp_name
, driver
->helpfile
);
1608 slprintf(driver
->helpfile
, sizeof(driver
->helpfile
)-1, "%s%s", directory
, temp_name
);
1611 if (driver
->dependentfiles
) {
1612 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1613 fstrcpy(temp_name
, driver
->dependentfiles
[i
]);
1614 slprintf(driver
->dependentfiles
[i
], sizeof(driver
->dependentfiles
[i
])-1, "%s%s", directory
, temp_name
);
1618 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, driver
->cversion
, driver
->name
);
1620 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key
));
1627 len
+= tdb_pack(buf
+len
, buflen
-len
, "dffffffff",
1630 driver
->environment
,
1635 driver
->monitorname
,
1636 driver
->defaultdatatype
);
1638 if (driver
->dependentfiles
) {
1639 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1640 len
+= tdb_pack(buf
+len
, buflen
-len
, "f",
1641 driver
->dependentfiles
[i
]);
1645 if (len
!= buflen
) {
1648 tb
= (char *)Realloc(buf
, len
);
1650 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1661 kbuf
.dsize
= strlen(key
)+1;
1665 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
1669 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key
));
1675 /****************************************************************************
1676 ****************************************************************************/
1677 static uint32
add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
)
1679 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3
;
1682 info3
.cversion
= driver
->version
;
1683 fstrcpy(info3
.name
,driver
->name
);
1684 fstrcpy(info3
.environment
,driver
->environment
);
1685 fstrcpy(info3
.driverpath
,driver
->driverpath
);
1686 fstrcpy(info3
.datafile
,driver
->datafile
);
1687 fstrcpy(info3
.configfile
,driver
->configfile
);
1688 fstrcpy(info3
.helpfile
,driver
->helpfile
);
1689 fstrcpy(info3
.monitorname
,driver
->monitorname
);
1690 fstrcpy(info3
.defaultdatatype
,driver
->defaultdatatype
);
1691 info3
.dependentfiles
= driver
->dependentfiles
;
1693 return add_a_printer_driver_3(&info3
);
1697 /****************************************************************************
1698 ****************************************************************************/
1699 static WERROR
get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, fstring driver
, fstring arch
)
1701 NT_PRINTER_DRIVER_INFO_LEVEL_3 info
;
1705 fstrcpy(info
.name
, driver
);
1706 fstrcpy(info
.defaultdatatype
, "RAW");
1708 fstrcpy(info
.driverpath
, "");
1709 fstrcpy(info
.datafile
, "");
1710 fstrcpy(info
.configfile
, "");
1711 fstrcpy(info
.helpfile
, "");
1713 if ((info
.dependentfiles
=(fstring
*)malloc(2*sizeof(fstring
))) == NULL
)
1716 memset(info
.dependentfiles
, '\0', 2*sizeof(fstring
));
1717 fstrcpy(info
.dependentfiles
[0], "");
1719 *info_ptr
= memdup(&info
, sizeof(info
));
1724 /****************************************************************************
1725 ****************************************************************************/
1726 static WERROR
get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, fstring drivername
, fstring arch
, uint32 version
)
1728 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver
;
1729 TDB_DATA kbuf
, dbuf
;
1730 fstring architecture
;
1735 ZERO_STRUCT(driver
);
1737 get_short_archi(architecture
, arch
);
1739 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX
, architecture
, version
, drivername
));
1741 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, version
, drivername
);
1744 kbuf
.dsize
= strlen(key
)+1;
1746 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
1748 return WERR_UNKNOWN_PRINTER_DRIVER
;
1750 len
+= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dffffffff",
1759 driver
.defaultdatatype
);
1762 while (len
< dbuf
.dsize
)
1766 tddfs
= (fstring
*)Realloc(driver
.dependentfiles
,
1767 sizeof(fstring
)*(i
+2));
1768 if (tddfs
== NULL
) {
1769 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1772 else driver
.dependentfiles
= tddfs
;
1774 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "f",
1775 &driver
.dependentfiles
[i
]);
1779 if (driver
.dependentfiles
!= NULL
)
1780 fstrcpy(driver
.dependentfiles
[i
], "");
1782 SAFE_FREE(dbuf
.dptr
);
1784 if (len
!= dbuf
.dsize
)
1786 SAFE_FREE(driver
.dependentfiles
);
1788 return get_a_printer_driver_3_default(info_ptr
, drivername
, arch
);
1791 *info_ptr
= (NT_PRINTER_DRIVER_INFO_LEVEL_3
*)memdup(&driver
, sizeof(driver
));
1796 /****************************************************************************
1797 ****************************************************************************/
1798 uint32
get_a_printer_driver_9x_compatible(pstring line
, fstring model
)
1800 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
1806 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, "WIN40", 0, model
);
1807 DEBUG(10,("driver key: [%s]\n", key
));
1810 kbuf
.dsize
= strlen(key
)+1;
1811 if (!tdb_exists(tdb_drivers
, kbuf
))
1815 get_a_printer_driver_3(&info3
, model
, "Windows 4.0", 0);
1817 DEBUGADD(10,("info3->name [%s]\n", info3
->name
));
1818 DEBUGADD(10,("info3->datafile [%s]\n", info3
->datafile
));
1819 DEBUGADD(10,("info3->helpfile [%s]\n", info3
->helpfile
));
1820 DEBUGADD(10,("info3->monitorname [%s]\n", info3
->monitorname
));
1821 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3
->defaultdatatype
));
1822 for (i
=0; info3
->dependentfiles
&& *info3
->dependentfiles
[i
]; i
++) {
1823 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3
->dependentfiles
[i
]));
1825 DEBUGADD(10,("info3->environment [%s]\n", info3
->environment
));
1826 DEBUGADD(10,("info3->driverpath [%s]\n", info3
->driverpath
));
1827 DEBUGADD(10,("info3->configfile [%s]\n", info3
->configfile
));
1829 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1830 trim_string(info3
->driverpath
, "\\print$\\WIN40\\0\\", 0);
1831 pstrcat(line
, info3
->driverpath
);
1833 trim_string(info3
->datafile
, "\\print$\\WIN40\\0\\", 0);
1834 pstrcat(line
, info3
->datafile
);
1836 trim_string(info3
->helpfile
, "\\print$\\WIN40\\0\\", 0);
1837 pstrcat(line
, info3
->helpfile
);
1839 trim_string(info3
->monitorname
, "\\print$\\WIN40\\0\\", 0);
1840 pstrcat(line
, info3
->monitorname
);
1842 pstrcat(line
, "RAW"); /*info3->defaultdatatype);*/
1845 for (i
=0; info3
->dependentfiles
&& *info3
->dependentfiles
[i
]; i
++) {
1847 pstrcat(line
, ","); /* don't end in a "," */
1848 trim_string(info3
->dependentfiles
[i
], "\\print$\\WIN40\\0\\", 0);
1849 pstrcat(line
, info3
->dependentfiles
[i
]);
1857 /****************************************************************************
1858 Debugging function, dump at level 6 the struct in the logs.
1859 ****************************************************************************/
1861 static uint32
dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
1864 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
1867 DEBUG(20,("Dumping printer driver at level [%d]\n", level
));
1873 if (driver
.info_3
== NULL
)
1876 info3
=driver
.info_3
;
1878 DEBUGADD(20,("version:[%d]\n", info3
->cversion
));
1879 DEBUGADD(20,("name:[%s]\n", info3
->name
));
1880 DEBUGADD(20,("environment:[%s]\n", info3
->environment
));
1881 DEBUGADD(20,("driverpath:[%s]\n", info3
->driverpath
));
1882 DEBUGADD(20,("datafile:[%s]\n", info3
->datafile
));
1883 DEBUGADD(20,("configfile:[%s]\n", info3
->configfile
));
1884 DEBUGADD(20,("helpfile:[%s]\n", info3
->helpfile
));
1885 DEBUGADD(20,("monitorname:[%s]\n", info3
->monitorname
));
1886 DEBUGADD(20,("defaultdatatype:[%s]\n", info3
->defaultdatatype
));
1888 for (i
=0; info3
->dependentfiles
&&
1889 *info3
->dependentfiles
[i
]; i
++) {
1890 DEBUGADD(20,("dependentfile:[%s]\n",
1891 info3
->dependentfiles
[i
]));
1898 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level
));
1906 /****************************************************************************
1907 ****************************************************************************/
1908 int pack_devicemode(NT_DEVICEMODE
*nt_devmode
, char *buf
, int buflen
)
1912 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", nt_devmode
);
1914 if (!nt_devmode
) return len
;
1916 len
+= tdb_pack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1917 nt_devmode
->devicename
,
1918 nt_devmode
->formname
,
1920 nt_devmode
->specversion
,
1921 nt_devmode
->driverversion
,
1923 nt_devmode
->driverextra
,
1924 nt_devmode
->orientation
,
1925 nt_devmode
->papersize
,
1926 nt_devmode
->paperlength
,
1927 nt_devmode
->paperwidth
,
1930 nt_devmode
->defaultsource
,
1931 nt_devmode
->printquality
,
1934 nt_devmode
->yresolution
,
1935 nt_devmode
->ttoption
,
1936 nt_devmode
->collate
,
1937 nt_devmode
->logpixels
,
1940 nt_devmode
->bitsperpel
,
1941 nt_devmode
->pelswidth
,
1942 nt_devmode
->pelsheight
,
1943 nt_devmode
->displayflags
,
1944 nt_devmode
->displayfrequency
,
1945 nt_devmode
->icmmethod
,
1946 nt_devmode
->icmintent
,
1947 nt_devmode
->mediatype
,
1948 nt_devmode
->dithertype
,
1949 nt_devmode
->reserved1
,
1950 nt_devmode
->reserved2
,
1951 nt_devmode
->panningwidth
,
1952 nt_devmode
->panningheight
,
1953 nt_devmode
->private);
1956 if (nt_devmode
->private) {
1957 len
+= tdb_pack(buf
+len
, buflen
-len
, "B",
1958 nt_devmode
->driverextra
,
1959 nt_devmode
->private);
1962 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode
->formname
));
1967 /****************************************************************************
1968 Pack all values in all printer keys
1969 ***************************************************************************/
1971 static int pack_values(NT_PRINTER_DATA
*data
, char *buf
, int buflen
)
1975 REGISTRY_VALUE
*val
;
1976 REGVAL_CTR
*val_ctr
;
1983 /* loop over all keys */
1985 for ( i
=0; i
<data
->num_keys
; i
++ )
1987 val_ctr
= &data
->keys
[i
].values
;
1988 num_values
= regval_ctr_numvals( val_ctr
);
1990 /* loop over all values */
1992 for ( j
=0; j
<num_values
; j
++ )
1994 /* pathname should be stored as <key>\<value> */
1996 val
= regval_ctr_specific_value( val_ctr
, j
);
1997 pstrcpy( path
, data
->keys
[i
].name
);
1998 pstrcat( path
, "\\" );
1999 pstrcat( path
, regval_name(val
) );
2001 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2006 regval_data_p(val
) );
2013 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", NULL
);
2019 /****************************************************************************
2020 Delete a printer - this just deletes the printer info file, any open
2021 handles are not affected.
2022 ****************************************************************************/
2024 uint32
del_a_printer(char *sharename
)
2029 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
2032 kbuf
.dsize
=strlen(key
)+1;
2034 tdb_delete(tdb_printers
, kbuf
);
2038 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
2039 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
**, fstring
);
2040 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**);
2041 /****************************************************************************
2042 ****************************************************************************/
2043 static WERROR
update_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
)
2049 TDB_DATA kbuf
, dbuf
;
2052 * in addprinter: no servername and the printer is the name
2053 * in setprinter: servername is \\server
2054 * and printer is \\server\\printer
2056 * Samba manages only local printers.
2057 * we currently don't support things like path=\\other_server\printer
2060 if (info
->servername
[0]!='\0') {
2061 trim_string(info
->printername
, info
->servername
, NULL
);
2062 trim_string(info
->printername
, "\\", NULL
);
2063 info
->servername
[0]='\0';
2067 * JFM: one day I'll forget.
2068 * below that's info->portname because that's the SAMBA sharename
2069 * and I made NT 'thinks' it's the portname
2070 * the info->sharename is the thing you can name when you add a printer
2071 * that's the short-name when you create shared printer for 95/98
2072 * So I've made a limitation in SAMBA: you can only have 1 printer model
2073 * behind a SAMBA share.
2081 len
+= tdb_pack(buf
+len
, buflen
-len
, "dddddddddddfffffPfffff",
2084 info
->default_priority
,
2101 info
->printprocessor
,
2105 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
2107 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
2109 if (buflen
!= len
) {
2112 tb
= (char *)Realloc(buf
, len
);
2114 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2124 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, info
->sharename
);
2127 kbuf
.dsize
= strlen(key
)+1;
2131 ret
= (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) == 0? WERR_OK
: WERR_NOMEM
);
2134 if (!W_ERROR_IS_OK(ret
))
2135 DEBUG(8, ("error updating printer to tdb on disk\n"));
2139 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2140 info
->sharename
, info
->drivername
, info
->portname
, len
));
2146 /****************************************************************************
2147 Malloc and return an NT devicemode.
2148 ****************************************************************************/
2150 NT_DEVICEMODE
*construct_nt_devicemode(const fstring default_devicename
)
2154 NT_DEVICEMODE
*nt_devmode
= (NT_DEVICEMODE
*)malloc(sizeof(NT_DEVICEMODE
));
2156 if (nt_devmode
== NULL
) {
2157 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2161 ZERO_STRUCTP(nt_devmode
);
2163 safe_strcpy(adevice
, default_devicename
, sizeof(adevice
));
2164 fstrcpy(nt_devmode
->devicename
, adevice
);
2166 fstrcpy(nt_devmode
->formname
, "Letter");
2168 nt_devmode
->specversion
= 0x0401;
2169 nt_devmode
->driverversion
= 0x0400;
2170 nt_devmode
->size
= 0x00DC;
2171 nt_devmode
->driverextra
= 0x0000;
2172 nt_devmode
->fields
= FORMNAME
| TTOPTION
| PRINTQUALITY
|
2173 DEFAULTSOURCE
| COPIES
| SCALE
|
2174 PAPERSIZE
| ORIENTATION
;
2175 nt_devmode
->orientation
= 1;
2176 nt_devmode
->papersize
= PAPER_LETTER
;
2177 nt_devmode
->paperlength
= 0;
2178 nt_devmode
->paperwidth
= 0;
2179 nt_devmode
->scale
= 0x64;
2180 nt_devmode
->copies
= 1;
2181 nt_devmode
->defaultsource
= BIN_FORMSOURCE
;
2182 nt_devmode
->printquality
= RES_HIGH
; /* 0x0258 */
2183 nt_devmode
->color
= COLOR_MONOCHROME
;
2184 nt_devmode
->duplex
= DUP_SIMPLEX
;
2185 nt_devmode
->yresolution
= 0;
2186 nt_devmode
->ttoption
= TT_SUBDEV
;
2187 nt_devmode
->collate
= COLLATE_FALSE
;
2188 nt_devmode
->icmmethod
= 0;
2189 nt_devmode
->icmintent
= 0;
2190 nt_devmode
->mediatype
= 0;
2191 nt_devmode
->dithertype
= 0;
2193 /* non utilisés par un driver d'imprimante */
2194 nt_devmode
->logpixels
= 0;
2195 nt_devmode
->bitsperpel
= 0;
2196 nt_devmode
->pelswidth
= 0;
2197 nt_devmode
->pelsheight
= 0;
2198 nt_devmode
->displayflags
= 0;
2199 nt_devmode
->displayfrequency
= 0;
2200 nt_devmode
->reserved1
= 0;
2201 nt_devmode
->reserved2
= 0;
2202 nt_devmode
->panningwidth
= 0;
2203 nt_devmode
->panningheight
= 0;
2205 nt_devmode
->private = NULL
;
2209 /****************************************************************************
2210 Deepcopy an NT devicemode.
2211 ****************************************************************************/
2213 NT_DEVICEMODE
*dup_nt_devicemode(NT_DEVICEMODE
*nt_devicemode
)
2215 NT_DEVICEMODE
*new_nt_devicemode
= NULL
;
2217 if ((new_nt_devicemode
= (NT_DEVICEMODE
*)memdup(nt_devicemode
, sizeof(NT_DEVICEMODE
))) == NULL
) {
2218 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2222 new_nt_devicemode
->private = NULL
;
2223 if (nt_devicemode
->private != NULL
) {
2224 if ((new_nt_devicemode
->private = memdup(nt_devicemode
->private, nt_devicemode
->driverextra
)) == NULL
) {
2225 SAFE_FREE(new_nt_devicemode
);
2226 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2231 return new_nt_devicemode
;
2234 /****************************************************************************
2235 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2236 ****************************************************************************/
2238 void free_nt_devicemode(NT_DEVICEMODE
**devmode_ptr
)
2240 NT_DEVICEMODE
*nt_devmode
= *devmode_ptr
;
2242 if(nt_devmode
== NULL
)
2245 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2247 SAFE_FREE(nt_devmode
->private);
2248 SAFE_FREE(*devmode_ptr
);
2251 /****************************************************************************
2252 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2253 ****************************************************************************/
2254 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
)
2256 NT_PRINTER_INFO_LEVEL_2
*info
= *info_ptr
;
2257 NT_PRINTER_DATA
*data
;
2263 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2265 free_nt_devicemode(&info
->devmode
);
2267 /* clean up all registry keys */
2270 for ( i
=0; i
<data
->num_keys
; i
++ )
2272 SAFE_FREE( data
->keys
[i
].name
);
2273 regval_ctr_destroy( &data
->keys
[i
].values
);
2275 SAFE_FREE( data
->keys
);
2277 /* finally the top level structure */
2279 SAFE_FREE( *info_ptr
);
2283 /****************************************************************************
2284 ****************************************************************************/
2285 int unpack_devicemode(NT_DEVICEMODE
**nt_devmode
, char *buf
, int buflen
)
2289 NT_DEVICEMODE devmode
;
2291 ZERO_STRUCT(devmode
);
2293 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2295 if (!*nt_devmode
) return len
;
2297 len
+= tdb_unpack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2301 &devmode
.specversion
,
2302 &devmode
.driverversion
,
2304 &devmode
.driverextra
,
2305 &devmode
.orientation
,
2307 &devmode
.paperlength
,
2308 &devmode
.paperwidth
,
2311 &devmode
.defaultsource
,
2312 &devmode
.printquality
,
2315 &devmode
.yresolution
,
2321 &devmode
.bitsperpel
,
2323 &devmode
.pelsheight
,
2324 &devmode
.displayflags
,
2325 &devmode
.displayfrequency
,
2329 &devmode
.dithertype
,
2332 &devmode
.panningwidth
,
2333 &devmode
.panningheight
,
2336 if (devmode
.private) {
2337 /* the len in tdb_unpack is an int value and
2338 * devmode.driverextra is only a short
2340 len
+= tdb_unpack(buf
+len
, buflen
-len
, "B", &extra_len
, &devmode
.private);
2341 devmode
.driverextra
=(uint16
)extra_len
;
2343 /* check to catch an invalid TDB entry so we don't segfault */
2344 if (devmode
.driverextra
== 0) {
2345 devmode
.private = NULL
;
2349 *nt_devmode
= (NT_DEVICEMODE
*)memdup(&devmode
, sizeof(devmode
));
2351 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode
.devicename
, devmode
.formname
));
2352 if (devmode
.private)
2353 DEBUG(8,("with a private section of %d bytes\n", devmode
.driverextra
));
2358 /****************************************************************************
2359 allocate and initialize a new slot in
2360 ***************************************************************************/
2362 static int add_new_printer_key( NT_PRINTER_DATA
*data
, char *name
)
2367 if ( !data
|| !name
)
2370 /* allocate another slot in the NT_PRINTER_KEY array */
2372 d
= Realloc( data
->keys
, sizeof(NT_PRINTER_KEY
)*(data
->num_keys
+1) );
2376 key_index
= data
->num_keys
;
2378 /* initialze new key */
2381 data
->keys
[key_index
].name
= strdup( name
);
2383 ZERO_STRUCTP( &data
->keys
[key_index
].values
);
2385 regval_ctr_init( &data
->keys
[key_index
].values
);
2387 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name
));
2392 /****************************************************************************
2393 search for a registry key name in the existing printer data
2394 ***************************************************************************/
2396 int lookup_printerkey( NT_PRINTER_DATA
*data
, char *name
)
2401 if ( !data
|| !name
)
2404 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name
));
2406 /* loop over all existing keys */
2408 for ( i
=0; i
<data
->num_keys
; i
++ )
2410 if ( strequal(data
->keys
[i
].name
, name
) ) {
2411 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name
));
2421 /****************************************************************************
2422 ***************************************************************************/
2424 uint32
get_printer_subkeys( NT_PRINTER_DATA
*data
, char* key
, fstring
**subkeys
)
2428 int num_subkeys
= 0;
2430 fstring
*ptr
, *subkeys_ptr
= NULL
;
2436 for ( i
=0; i
<data
->num_keys
; i
++ )
2438 if ( StrnCaseCmp(data
->keys
[i
].name
, key
, strlen(key
)) == 0 )
2440 /* match sure it is a subkey and not the key itself */
2442 key_len
= strlen( key
);
2443 if ( strlen(data
->keys
[i
].name
) == key_len
)
2446 /* get subkey path */
2448 p
= data
->keys
[i
].name
+ key_len
;
2451 fstrcpy( subkeyname
, p
);
2452 if ( (p
= strchr( subkeyname
, '\\' )) )
2455 /* don't add a key more than once */
2457 for ( j
=0; j
<num_subkeys
; j
++ ) {
2458 if ( strequal( subkeys_ptr
[j
], subkeyname
) )
2462 if ( j
!= num_subkeys
)
2465 /* found a match, so allocate space and copy the name */
2467 if ( !(ptr
= Realloc( subkeys_ptr
, (num_subkeys
+2)*sizeof(fstring
))) ) {
2468 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2470 SAFE_FREE( subkeys
);
2475 fstrcpy( subkeys_ptr
[num_subkeys
], subkeyname
);
2481 /* tag of the end */
2483 fstrcpy( subkeys_ptr
[num_subkeys
], "" );
2485 *subkeys
= subkeys_ptr
;
2490 /****************************************************************************
2491 ***************************************************************************/
2493 WERROR
delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, char *key
)
2495 NT_PRINTER_DATA
*data
;
2497 int removed_keys
= 0;
2501 empty_slot
= data
->num_keys
;
2504 return WERR_INVALID_PARAM
;
2506 /* remove all keys */
2510 for ( i
=0; i
<data
->num_keys
; i
++ )
2512 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2513 data
->keys
[i
].name
));
2515 SAFE_FREE( data
->keys
[i
].name
);
2516 regval_ctr_destroy( &data
->keys
[i
].values
);
2519 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2522 SAFE_FREE( data
->keys
);
2523 ZERO_STRUCTP( data
);
2528 /* remove a specific key (and all subkeys) */
2530 for ( i
=0; i
<data
->num_keys
; i
++ )
2532 if ( StrnCaseCmp( data
->keys
[i
].name
, key
, strlen(key
)) == 0 )
2534 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2535 data
->keys
[i
].name
));
2537 SAFE_FREE( data
->keys
[i
].name
);
2538 regval_ctr_destroy( &data
->keys
[i
].values
);
2540 /* mark the slot as empty */
2542 ZERO_STRUCTP( &data
->keys
[i
] );
2546 /* find the first empty slot */
2548 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2549 if ( !data
->keys
[i
].name
) {
2556 if ( i
== data
->num_keys
)
2557 /* nothing was removed */
2558 return WERR_INVALID_PARAM
;
2560 /* move everything down */
2562 for ( i
=empty_slot
+1; i
<data
->num_keys
; i
++ ) {
2563 if ( data
->keys
[i
].name
) {
2564 memcpy( &data
->keys
[empty_slot
], &data
->keys
[i
], sizeof(NT_PRINTER_KEY
) );
2565 ZERO_STRUCTP( &data
->keys
[i
] );
2573 data
->num_keys
-= removed_keys
;
2575 /* sanity check to see if anything is left */
2577 if ( !data
->num_keys
)
2579 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2
->printername
));
2581 SAFE_FREE( data
->keys
);
2582 ZERO_STRUCTP( data
);
2588 /****************************************************************************
2589 ***************************************************************************/
2591 WERROR
delete_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, char *key
, char *value
)
2593 WERROR result
= WERR_OK
;
2596 /* we must have names on non-zero length */
2598 if ( !key
|| !*key
|| !value
|| !*value
)
2599 return WERR_INVALID_NAME
;
2601 /* find the printer key first */
2603 key_index
= lookup_printerkey( &p2
->data
, key
);
2604 if ( key_index
== -1 )
2607 regval_ctr_delvalue( &p2
->data
.keys
[key_index
].values
, value
);
2609 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2615 /****************************************************************************
2616 ***************************************************************************/
2618 WERROR
add_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, char *key
, char *value
,
2619 uint32 type
, uint8
*data
, int real_len
)
2621 WERROR result
= WERR_OK
;
2624 /* we must have names on non-zero length */
2626 if ( !key
|| !*key
|| !value
|| !*value
)
2627 return WERR_INVALID_NAME
;
2629 /* find the printer key first */
2631 key_index
= lookup_printerkey( &p2
->data
, key
);
2632 if ( key_index
== -1 )
2633 key_index
= add_new_printer_key( &p2
->data
, key
);
2635 if ( key_index
== -1 )
2638 regval_ctr_addvalue( &p2
->data
.keys
[key_index
].values
, value
,
2639 type
, data
, real_len
);
2641 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
2642 key
, value
, type
, real_len
));
2647 /****************************************************************************
2648 ***************************************************************************/
2650 REGISTRY_VALUE
* get_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, char *key
, char *value
)
2654 if ( (key_index
= lookup_printerkey( &p2
->data
, key
)) == -1 )
2657 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
2660 return regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
);
2663 /****************************************************************************
2664 Unpack a list of registry values frem the TDB
2665 ***************************************************************************/
2667 static int unpack_values(NT_PRINTER_DATA
*printer_data
, char *buf
, int buflen
)
2671 pstring string
, valuename
, keyname
;
2675 REGISTRY_VALUE
*regval_p
;
2678 /* add the "PrinterDriverData" key first for performance reasons */
2680 add_new_printer_key( printer_data
, SPOOL_PRINTERDATA_KEY
);
2682 /* loop and unpack the rest of the registry values */
2687 /* check to see if there are any more registry values */
2689 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", ®val_p
);
2693 /* unpack the next regval */
2695 len
+= tdb_unpack(buf
+len
, buflen
-len
, "fdB",
2702 * break of the keyname from the value name.
2703 * Should only be one '\' in the string returned.
2706 str
= strrchr( string
, '\\');
2708 /* Put in "PrinterDriverData" is no key specified */
2711 pstrcpy( keyname
, SPOOL_PRINTERDATA_KEY
);
2712 pstrcpy( valuename
, string
);
2716 pstrcpy( keyname
, string
);
2717 pstrcpy( valuename
, str
+1 );
2720 /* see if we need a new key */
2722 if ( (key_index
=lookup_printerkey( printer_data
, keyname
)) == -1 )
2723 key_index
= add_new_printer_key( printer_data
, keyname
);
2725 if ( key_index
== -1 ) {
2726 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
2731 /* add the new value */
2733 regval_ctr_addvalue( &printer_data
->keys
[key_index
].values
, valuename
, type
, data_p
, size
);
2735 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname
, valuename
, size
));
2741 /****************************************************************************
2742 ***************************************************************************/
2744 static void map_to_os2_driver(fstring drivername
)
2746 static BOOL initialised
=False
;
2747 static fstring last_from
,last_to
;
2748 char *mapfile
= lp_os2_driver_map();
2749 char **lines
= NULL
;
2753 if (!strlen(drivername
))
2760 *last_from
= *last_to
= 0;
2764 if (strequal(drivername
,last_from
)) {
2765 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,last_to
));
2766 fstrcpy(drivername
,last_to
);
2770 lines
= file_lines_load(mapfile
, &numlines
);
2771 if (numlines
== 0) {
2772 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile
));
2776 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
2778 for( i
= 0; i
< numlines
; i
++) {
2779 char *nt_name
= lines
[i
];
2780 char *os2_name
= strchr(nt_name
,'=');
2787 while (isspace(*nt_name
))
2790 if (!*nt_name
|| strchr("#;",*nt_name
))
2794 int l
= strlen(nt_name
);
2795 while (l
&& isspace(nt_name
[l
-1])) {
2801 while (isspace(*os2_name
))
2805 int l
= strlen(os2_name
);
2806 while (l
&& isspace(os2_name
[l
-1])) {
2812 if (strequal(nt_name
,drivername
)) {
2813 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername
,os2_name
));
2814 fstrcpy(last_from
,drivername
);
2815 fstrcpy(last_to
,os2_name
);
2816 fstrcpy(drivername
,os2_name
);
2817 file_lines_free(lines
);
2822 file_lines_free(lines
);
2825 /****************************************************************************
2826 get a default printer info 2 struct
2827 ****************************************************************************/
2828 static WERROR
get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, fstring sharename
)
2831 NT_PRINTER_INFO_LEVEL_2 info
;
2835 snum
= lp_servicenumber(sharename
);
2837 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", get_called_name());
2838 slprintf(info
.printername
, sizeof(info
.printername
)-1, "\\\\%s\\%s",
2839 get_called_name(), sharename
);
2840 fstrcpy(info
.sharename
, sharename
);
2841 fstrcpy(info
.portname
, SAMBA_PRINTER_PORT_NAME
);
2842 fstrcpy(info
.drivername
, lp_printerdriver(snum
));
2844 /* by setting the driver name to an empty string, a local NT admin
2845 can now run the **local** APW to install a local printer driver
2846 for a Samba shared printer in 2.2. Without this, drivers **must** be
2847 installed on the Samba server for NT clients --jerry */
2848 #if 0 /* JERRY --do not uncomment-- */
2849 if (!*info
.drivername
)
2850 fstrcpy(info
.drivername
, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2854 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info
.drivername
));
2856 pstrcpy(info
.comment
, "");
2857 fstrcpy(info
.printprocessor
, "winprint");
2858 fstrcpy(info
.datatype
, "RAW");
2860 info
.attributes
= PRINTER_ATTRIBUTE_SHARED
| PRINTER_ATTRIBUTE_NETWORK
; /* attributes */
2862 info
.starttime
= 0; /* Minutes since 12:00am GMT */
2863 info
.untiltime
= 0; /* Minutes since 12:00am GMT */
2865 info
.default_priority
= 1;
2866 info
.setuptime
= (uint32
)time(NULL
);
2869 * I changed this as I think it is better to have a generic
2870 * DEVMODE than to crash Win2k explorer.exe --jerry
2871 * See the HP Deskjet 990c Win2k drivers for an example.
2873 * However the default devmode appears to cause problems
2874 * with the HP CLJ 8500 PCL driver. Hence the addition of
2875 * the "default devmode" parameter --jerry 22/01/2002
2878 if (lp_default_devmode(snum
)) {
2879 if ((info
.devmode
= construct_nt_devicemode(info
.printername
)) == NULL
)
2883 info
.devmode
= NULL
;
2886 /* This will get the current RPC talloc context, but we should be
2887 passing this as a parameter... fixme... JRA ! */
2889 if (!nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
))
2892 *info_ptr
= (NT_PRINTER_INFO_LEVEL_2
*)memdup(&info
, sizeof(info
));
2894 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2902 free_nt_devicemode(&info
.devmode
);
2903 return WERR_ACCESS_DENIED
;
2906 /****************************************************************************
2907 ****************************************************************************/
2908 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, fstring sharename
)
2911 NT_PRINTER_INFO_LEVEL_2 info
;
2913 TDB_DATA kbuf
, dbuf
;
2914 fstring printername
;
2918 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
2921 kbuf
.dsize
= strlen(key
)+1;
2923 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
2925 return get_a_printer_2_default(info_ptr
, sharename
);
2927 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "dddddddddddfffffPfffff",
2930 &info
.default_priority
,
2947 info
.printprocessor
,
2951 /* Samba has to have shared raw drivers. */
2952 info
.attributes
|= (PRINTER_ATTRIBUTE_SHARED
| PRINTER_ATTRIBUTE_NETWORK
);
2954 /* Restore the stripped strings. */
2955 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", get_called_name());
2956 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", get_called_name(),
2958 fstrcpy(info
.printername
, printername
);
2960 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
2963 * Some client drivers freak out if there is a NULL devmode
2964 * (probably the driver is not checking before accessing
2965 * the devmode pointer) --jerry
2967 * See comments in get_a_printer_2_default()
2970 if (lp_default_devmode(lp_servicenumber(sharename
)) && !info
.devmode
)
2972 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
2974 info
.devmode
= construct_nt_devicemode(printername
);
2977 len
+= unpack_values( &info
.data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
2979 /* This will get the current RPC talloc context, but we should be
2980 passing this as a parameter... fixme... JRA ! */
2982 nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
);
2984 /* Fix for OS/2 drivers. */
2986 if (get_remote_arch() == RA_OS2
)
2987 map_to_os2_driver(info
.drivername
);
2989 SAFE_FREE(dbuf
.dptr
);
2990 *info_ptr
=memdup(&info
, sizeof(info
));
2992 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2993 sharename
, info
.printername
, info
.drivername
));
2998 /****************************************************************************
2999 debugging function, dump at level 6 the struct in the logs
3000 ****************************************************************************/
3001 static uint32
dump_a_printer(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3004 NT_PRINTER_INFO_LEVEL_2
*info2
;
3006 DEBUG(106,("Dumping printer at level [%d]\n", level
));
3012 if (printer
.info_2
== NULL
)
3016 info2
=printer
.info_2
;
3018 DEBUGADD(106,("attributes:[%d]\n", info2
->attributes
));
3019 DEBUGADD(106,("priority:[%d]\n", info2
->priority
));
3020 DEBUGADD(106,("default_priority:[%d]\n", info2
->default_priority
));
3021 DEBUGADD(106,("starttime:[%d]\n", info2
->starttime
));
3022 DEBUGADD(106,("untiltime:[%d]\n", info2
->untiltime
));
3023 DEBUGADD(106,("status:[%d]\n", info2
->status
));
3024 DEBUGADD(106,("cjobs:[%d]\n", info2
->cjobs
));
3025 DEBUGADD(106,("averageppm:[%d]\n", info2
->averageppm
));
3026 DEBUGADD(106,("changeid:[%d]\n", info2
->changeid
));
3027 DEBUGADD(106,("c_setprinter:[%d]\n", info2
->c_setprinter
));
3028 DEBUGADD(106,("setuptime:[%d]\n", info2
->setuptime
));
3030 DEBUGADD(106,("servername:[%s]\n", info2
->servername
));
3031 DEBUGADD(106,("printername:[%s]\n", info2
->printername
));
3032 DEBUGADD(106,("sharename:[%s]\n", info2
->sharename
));
3033 DEBUGADD(106,("portname:[%s]\n", info2
->portname
));
3034 DEBUGADD(106,("drivername:[%s]\n", info2
->drivername
));
3035 DEBUGADD(106,("comment:[%s]\n", info2
->comment
));
3036 DEBUGADD(106,("location:[%s]\n", info2
->location
));
3037 DEBUGADD(106,("sepfile:[%s]\n", info2
->sepfile
));
3038 DEBUGADD(106,("printprocessor:[%s]\n", info2
->printprocessor
));
3039 DEBUGADD(106,("datatype:[%s]\n", info2
->datatype
));
3040 DEBUGADD(106,("parameters:[%s]\n", info2
->parameters
));
3046 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level
));
3054 /****************************************************************************
3055 Get the parameters we can substitute in an NT print job.
3056 ****************************************************************************/
3058 void get_printer_subst_params(int snum
, fstring
*printername
, fstring
*sharename
, fstring
*portname
)
3060 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3062 **printername
= **sharename
= **portname
= '\0';
3064 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3067 fstrcpy(*printername
, printer
->info_2
->printername
);
3068 fstrcpy(*sharename
, printer
->info_2
->sharename
);
3069 fstrcpy(*portname
, printer
->info_2
->portname
);
3071 free_a_printer(&printer
, 2);
3074 /****************************************************************************
3075 Update the changeid time.
3076 This is SO NASTY as some drivers need this to change, others need it
3077 static. This value will change every second, and I must hope that this
3078 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3080 ****************************************************************************/
3082 static uint32
rev_changeid(void)
3086 get_process_uptime(&tv
);
3089 /* Return changeid as msec since spooler restart */
3090 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
3093 * This setting seems to work well but is too untested
3094 * to replace the above calculation. Left in for experiementation
3095 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3097 return tv
.tv_sec
* 10 + tv
.tv_usec
/ 100000;
3102 * The function below are the high level ones.
3103 * only those ones must be called from the spoolss code.
3107 /****************************************************************************
3108 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3109 ****************************************************************************/
3111 WERROR
mod_a_printer(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3115 dump_a_printer(printer
, level
);
3122 * Update the changestamp. Emperical tests show that the
3123 * ChangeID is always updated,but c_setprinter is
3124 * global spooler variable (not per printer).
3127 /* ChangeID **must** be increasing over the lifetime
3128 of client's spoolss service in order for the
3129 client's cache to show updates */
3131 printer
.info_2
->changeid
= rev_changeid();
3134 * Because one day someone will ask:
3135 * NT->NT An admin connection to a remote
3136 * printer show changes imeediately in
3137 * the properities dialog
3139 * A non-admin connection will only show the
3140 * changes after viewing the properites page
3141 * 2 times. Seems to be related to a
3142 * race condition in the client between the spooler
3143 * updating the local cache and the Explorer.exe GUI
3144 * actually displaying the properties.
3146 * This is fixed in Win2k. admin/non-admin
3147 * connections both display changes immediately.
3152 result
=update_a_printer_2(printer
.info_2
);
3156 result
=WERR_UNKNOWN_LEVEL
;
3163 /****************************************************************************
3164 Initialize printer devmode & data with previously saved driver init values.
3165 ****************************************************************************/
3167 static BOOL
set_driver_init_2( NT_PRINTER_INFO_LEVEL_2
*info_ptr
)
3171 TDB_DATA kbuf
, dbuf
;
3172 NT_PRINTER_INFO_LEVEL_2 info
;
3178 * Delete any printer data 'values' already set. When called for driver
3179 * replace, there will generally be some, but during an add printer, there
3180 * should not be any (if there are delete them).
3183 delete_all_printer_data( info_ptr
, "" );
3185 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info_ptr
->drivername
);
3188 kbuf
.dsize
= strlen(key
)+1;
3190 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
3193 * When changing to a driver that has no init info in the tdb, remove
3194 * the previous drivers init info and leave the new on blank.
3196 free_nt_devicemode(&info_ptr
->devmode
);
3201 * Get the saved DEVMODE..
3204 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3207 * The saved DEVMODE contains the devicename from the printer used during
3208 * the initialization save. Change it to reflect the new printer.
3211 if ( info
.devmode
) {
3212 ZERO_STRUCT(info
.devmode
->devicename
);
3213 fstrcpy(info
.devmode
->devicename
, info_ptr
->printername
);
3217 * NT/2k does not change out the entire DeviceMode of a printer
3218 * when changing the driver. Only the driverextra, private, &
3219 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3221 * Later examination revealed that Windows NT/2k does reset the
3222 * the printer's device mode, bit **only** when you change a
3223 * property of the device mode such as the page orientation.
3228 /* Bind the saved DEVMODE to the new the printer */
3230 free_nt_devicemode(&info_ptr
->devmode
);
3231 info_ptr
->devmode
= info
.devmode
;
3233 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3234 info_ptr
->printername
, info_ptr
->devmode
?"VALID":"NULL", info_ptr
->drivername
));
3236 /* Add the printer data 'values' to the new printer */
3238 len
+= unpack_values( &info_ptr
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3241 SAFE_FREE(dbuf
.dptr
);
3246 /****************************************************************************
3247 Initialize printer devmode & data with previously saved driver init values.
3248 When a printer is created using AddPrinter, the drivername bound to the
3249 printer is used to lookup previously saved driver initialization info, which
3250 is bound to the new printer.
3251 ****************************************************************************/
3253 BOOL
set_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3255 BOOL result
= False
;
3260 result
= set_driver_init_2(printer
->info_2
);
3264 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3272 /****************************************************************************
3273 Delete driver init data stored for a specified driver
3274 ****************************************************************************/
3276 BOOL
del_driver_init(char *drivername
)
3281 if (!drivername
|| !*drivername
) {
3282 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3286 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, drivername
);
3289 kbuf
.dsize
= strlen(key
)+1;
3291 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername
));
3293 return (tdb_delete(tdb_drivers
, kbuf
) == 0);
3296 /****************************************************************************
3297 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3298 in the tdb. Note: this is different from the driver entry and the printer
3299 entry. There should be a single driver init entry for each driver regardless
3300 of whether it was installed from NT or 2K. Technically, they should be
3301 different, but they work out to the same struct.
3302 ****************************************************************************/
3304 static uint32
update_driver_init_2(NT_PRINTER_INFO_LEVEL_2
*info
)
3308 int buflen
, len
, ret
;
3309 TDB_DATA kbuf
, dbuf
;
3316 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
3318 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
3320 if (buflen
!= len
) {
3323 tb
= (char *)Realloc(buf
, len
);
3325 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3334 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info
->drivername
);
3337 kbuf
.dsize
= strlen(key
)+1;
3341 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
3345 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3349 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3350 info
->sharename
, info
->drivername
));
3355 /****************************************************************************
3356 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3357 ****************************************************************************/
3359 uint32
update_driver_init(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3363 dump_a_printer(printer
, level
);
3369 result
= update_driver_init_2(printer
.info_2
);
3380 /****************************************************************************
3381 Convert the printer data value, a REG_BINARY array, into an initialization
3382 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3383 got to keep the endians happy :).
3384 ****************************************************************************/
3386 static BOOL
convert_driver_init( TALLOC_CTX
*ctx
, NT_DEVICEMODE
*nt_devmode
, uint8
*data
, uint32 data_len
)
3388 BOOL result
= False
;
3392 ZERO_STRUCT(devmode
);
3394 prs_init(&ps
, 0, ctx
, UNMARSHALL
);
3395 ps
.data_p
= (char *)data
;
3396 ps
.buffer_size
= data_len
;
3398 if (spoolss_io_devmode("phantom DEVMODE", &ps
, 0, &devmode
))
3399 result
= convert_devicemode("", &devmode
, &nt_devmode
);
3401 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3406 /****************************************************************************
3407 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3409 1. Use the driver's config DLL to this UNC printername and:
3410 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3411 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3412 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3414 The last step triggers saving the "driver initialization" information for
3415 this printer into the tdb. Later, new printers that use this driver will
3416 have this initialization information bound to them. This simulates the
3417 driver initialization, as if it had run on the Samba server (as it would
3420 The Win32 client side code requirement sucks! But until we can run arbitrary
3421 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3423 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3424 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3425 about it and you will realize why. JRR 010720
3426 ****************************************************************************/
3428 static WERROR
save_driver_init_2(NT_PRINTER_INFO_LEVEL
*printer
, uint8
*data
, uint32 data_len
)
3430 WERROR status
= WERR_OK
;
3431 TALLOC_CTX
*ctx
= NULL
;
3432 NT_DEVICEMODE
*nt_devmode
= NULL
;
3433 NT_DEVICEMODE
*tmp_devmode
= printer
->info_2
->devmode
;
3436 * When the DEVMODE is already set on the printer, don't try to unpack it.
3438 DEBUG(8,("save_driver_init_2: Enter...\n"));
3440 if ( !printer
->info_2
->devmode
&& data_len
)
3443 * Set devmode on printer info, so entire printer initialization can be
3447 if ((ctx
= talloc_init()) == NULL
)
3450 if ((nt_devmode
= (NT_DEVICEMODE
*)malloc(sizeof(NT_DEVICEMODE
))) == NULL
) {
3451 status
= WERR_NOMEM
;
3455 ZERO_STRUCTP(nt_devmode
);
3458 * The DEVMODE is held in the 'data' component of the param in raw binary.
3459 * Convert it to to a devmode structure
3461 if ( !convert_driver_init( ctx
, nt_devmode
, data
, data_len
)) {
3462 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3463 status
= WERR_INVALID_PARAM
;
3467 printer
->info_2
->devmode
= nt_devmode
;
3471 * Pack up and add (or update) the DEVMODE and any current printer data to
3472 * a 'driver init' element in the tdb
3476 if ( update_driver_init(*printer
, 2) != 0 ) {
3477 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3478 status
= WERR_NOMEM
;
3483 * If driver initialization info was successfully saved, set the current
3484 * printer to match it. This allows initialization of the current printer
3485 * as well as the driver.
3487 status
= mod_a_printer(*printer
, 2);
3488 if (!W_ERROR_IS_OK(status
)) {
3489 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3490 printer
->info_2
->printername
));
3494 talloc_destroy(ctx
);
3495 free_nt_devicemode( &nt_devmode
);
3497 printer
->info_2
->devmode
= tmp_devmode
;
3502 /****************************************************************************
3503 Update the driver init info (DEVMODE and specifics) for a printer
3504 ****************************************************************************/
3506 WERROR
save_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
, uint8
*data
, uint32 data_len
)
3508 WERROR status
= WERR_OK
;
3514 status
= save_driver_init_2( printer
, data
, data_len
);
3518 status
= WERR_UNKNOWN_LEVEL
;
3525 /****************************************************************************
3526 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3527 ****************************************************************************/
3529 WERROR
get_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
, fstring sharename
)
3532 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3536 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename
, (unsigned int)level
));
3542 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
3543 DEBUG(0,("get_a_printer: malloc fail.\n"));
3546 ZERO_STRUCTP(printer
);
3547 result
=get_a_printer_2(&printer
->info_2
, sharename
);
3548 if (W_ERROR_IS_OK(result
)) {
3549 dump_a_printer(*printer
, level
);
3550 *pp_printer
= printer
;
3557 result
=WERR_UNKNOWN_LEVEL
;
3561 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename
, (unsigned int)level
, dos_errstr(result
)));
3566 /****************************************************************************
3567 Deletes a NT_PRINTER_INFO_LEVEL struct.
3568 ****************************************************************************/
3570 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
3573 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
3575 DEBUG(104,("freeing a printer at level [%d]\n", level
));
3577 if (printer
== NULL
)
3584 if (printer
->info_2
!= NULL
)
3586 free_nt_printer_info_level_2(&printer
->info_2
);
3600 SAFE_FREE(*pp_printer
);
3604 /****************************************************************************
3605 ****************************************************************************/
3606 uint32
add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
3609 DEBUG(104,("adding a printer at level [%d]\n", level
));
3610 dump_a_printer_driver(driver
, level
);
3616 result
=add_a_printer_driver_3(driver
.info_3
);
3622 result
=add_a_printer_driver_6(driver
.info_6
);
3632 /****************************************************************************
3633 ****************************************************************************/
3634 WERROR
get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL
*driver
, uint32 level
,
3635 fstring drivername
, fstring architecture
, uint32 version
)
3642 /* Sometime we just want any version of the driver */
3644 if ( version
== DRIVER_ANY_VERSION
) {
3645 /* look for Win2k first and then for NT4 */
3646 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
3649 if ( !W_ERROR_IS_OK(result
) ) {
3650 result
= get_a_printer_driver_3( &driver
->info_3
,
3651 drivername
, architecture
, 2 );
3655 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
3656 architecture
, version
);
3665 if (W_ERROR_IS_OK(result
))
3666 dump_a_printer_driver(*driver
, level
);
3671 /****************************************************************************
3672 ****************************************************************************/
3673 uint32
free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
3681 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
3682 if (driver
.info_3
!= NULL
)
3684 info3
=driver
.info_3
;
3685 SAFE_FREE(info3
->dependentfiles
);
3686 ZERO_STRUCTP(info3
);
3698 NT_PRINTER_DRIVER_INFO_LEVEL_6
*info6
;
3699 if (driver
.info_6
!= NULL
)
3701 info6
=driver
.info_6
;
3702 SAFE_FREE(info6
->dependentfiles
);
3703 SAFE_FREE(info6
->previousnames
);
3704 ZERO_STRUCTP(info6
);
3722 /****************************************************************************
3723 Determine whether or not a particular driver is currently assigned
3725 ****************************************************************************/
3727 BOOL
printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
)
3730 int n_services
= lp_numservices();
3731 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3736 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
3738 /* loop through the printers.tdb and check for the drivername */
3740 for (snum
=0; snum
<n_services
; snum
++)
3742 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
3745 if ( !W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))) )
3748 if ( !StrCaseCmp(info_3
->name
, printer
->info_2
->drivername
) ) {
3749 free_a_printer( &printer
, 2 );
3753 free_a_printer( &printer
, 2 );
3756 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
3758 /* report that the driver is not in use by default */
3764 /**********************************************************************
3765 Check to see if a ogiven file is in use by *info
3766 *********************************************************************/
3768 static BOOL
drv_file_in_use( char* file
, NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
3775 if ( strequal(file
, info
->driverpath
) )
3778 if ( strequal(file
, info
->datafile
) )
3781 if ( strequal(file
, info
->configfile
) )
3784 if ( strequal(file
, info
->helpfile
) )
3787 /* see of there are any dependent files to examine */
3789 if ( !info
->dependentfiles
)
3792 while ( *info
->dependentfiles
[i
] )
3794 if ( strequal(file
, info
->dependentfiles
[i
]) )
3804 /**********************************************************************
3805 Utility function to remove the dependent file pointed to by the
3806 input parameter from the list
3807 *********************************************************************/
3809 static void trim_dependent_file( fstring files
[], int idx
)
3812 /* bump everything down a slot */
3814 while( *files
[idx
+1] )
3816 fstrcpy( files
[idx
], files
[idx
+1] );
3825 /**********************************************************************
3826 Check if any of the files used by src are also used by drv
3827 *********************************************************************/
3829 static BOOL
trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*src
,
3830 NT_PRINTER_DRIVER_INFO_LEVEL_3
*drv
)
3832 BOOL in_use
= False
;
3838 /* check each file. Remove it from the src structure if it overlaps */
3840 if ( drv_file_in_use(src
->driverpath
, drv
) ) {
3842 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driverpath
));
3843 fstrcpy( src
->driverpath
, "" );
3846 if ( drv_file_in_use(src
->datafile
, drv
) ) {
3848 DEBUG(10,("Removing datafile [%s] from list\n", src
->datafile
));
3849 fstrcpy( src
->datafile
, "" );
3852 if ( drv_file_in_use(src
->configfile
, drv
) ) {
3854 DEBUG(10,("Removing configfile [%s] from list\n", src
->configfile
));
3855 fstrcpy( src
->configfile
, "" );
3858 if ( drv_file_in_use(src
->helpfile
, drv
) ) {
3860 DEBUG(10,("Removing helpfile [%s] from list\n", src
->helpfile
));
3861 fstrcpy( src
->helpfile
, "" );
3864 /* are there any dependentfiles to examine? */
3866 if ( !src
->dependentfiles
)
3869 while ( *src
->dependentfiles
[i
] )
3871 if ( drv_file_in_use(src
->dependentfiles
[i
], drv
) ) {
3873 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependentfiles
[i
]));
3874 trim_dependent_file( src
->dependentfiles
, i
);
3883 /****************************************************************************
3884 Determine whether or not a particular driver files are currently being
3885 used by any other driver.
3887 Return value is True if any files were in use by other drivers
3888 and False otherwise.
3890 Upon return, *info has been modified to only contain the driver files
3891 which are not in use
3892 ****************************************************************************/
3894 BOOL
printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
3899 fstring
*list
= NULL
;
3900 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
3905 version
= info
->cversion
;
3907 /* loop over all driver versions */
3909 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
3911 /* get the list of drivers */
3914 ndrivers
= get_ntdrivers(&list
, info
->environment
, version
);
3916 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
3917 ndrivers
, info
->environment
, version
));
3919 /* check each driver for overlap in files */
3921 for (i
=0; i
<ndrivers
; i
++)
3923 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
3925 ZERO_STRUCT(driver
);
3927 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, list
[i
],
3928 info
->environment
, version
)) )
3934 /* check if d2 uses any files from d1 */
3935 /* only if this is a different driver than the one being deleted */
3937 if ( !strequal(info
->name
, driver
.info_3
->name
) )
3939 if ( trim_overlap_drv_files(info
, driver
.info_3
) ) {
3940 free_a_printer_driver(driver
, 3);
3946 free_a_printer_driver(driver
, 3);
3951 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
3953 driver
.info_3
= info
;
3955 if ( DEBUGLEVEL
>= 20 )
3956 dump_a_printer_driver( driver
, 3 );
3961 /****************************************************************************
3962 Actually delete the driver files. Make sure that
3963 printer_driver_files_in_use() return False before calling
3965 ****************************************************************************/
3967 static BOOL
delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
)
3971 connection_struct
*conn
;
3978 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3
->name
, info_3
->cversion
));
3981 * Connect to the print$ share under the same account as the
3982 * user connected to the rpc pipe. Note we must be root to
3987 null_pw
= data_blob( NULL
, 0 );
3988 conn
= make_connection_with_chdir( "print$", null_pw
, "A:", user
->vuid
, &nt_status
);
3992 DEBUG(0,("delete_driver_files: Unable to connect\n"));
3996 /* Save who we are - we are temporarily becoming the connection user. */
3998 if ( !become_user(conn
, conn
->vuid
) ) {
3999 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4003 /* now delete the files; must strip the '\print$' string from
4006 if ( *info_3
->driverpath
) {
4007 if ( (s
= strchr( &info_3
->driverpath
[1], '\\' )) != NULL
) {
4008 DEBUG(10,("deleting driverfile [%s]\n", s
));
4009 unlink_internals(conn
, 0, s
);
4013 if ( *info_3
->configfile
) {
4014 if ( (s
= strchr( &info_3
->configfile
[1], '\\' )) != NULL
) {
4015 DEBUG(10,("deleting configfile [%s]\n", s
));
4016 unlink_internals(conn
, 0, s
);
4020 if ( *info_3
->datafile
) {
4021 if ( (s
= strchr( &info_3
->datafile
[1], '\\' )) != NULL
) {
4022 DEBUG(10,("deleting datafile [%s]\n", s
));
4023 unlink_internals(conn
, 0, s
);
4027 if ( *info_3
->helpfile
) {
4028 if ( (s
= strchr( &info_3
->helpfile
[1], '\\' )) != NULL
) {
4029 DEBUG(10,("deleting helpfile [%s]\n", s
));
4030 unlink_internals(conn
, 0, s
);
4034 /* check if we are done removing files */
4036 if ( info_3
->dependentfiles
)
4038 while ( *info_3
->dependentfiles
[i
] ) {
4041 /* bypass the "\print$" portion of the path */
4043 if ( (file
= strchr( info_3
->dependentfiles
[i
]+1, '\\' )) != NULL
)
4045 DEBUG(10,("deleting dependent file [%s]\n", file
));
4046 unlink_internals(conn
, 0, file
);
4058 /****************************************************************************
4059 Remove a printer driver from the TDB. This assumes that the the driver was
4060 previously looked up.
4061 ***************************************************************************/
4063 WERROR
delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
,
4064 uint32 version
, BOOL delete_files
)
4068 TDB_DATA kbuf
, dbuf
;
4069 NT_PRINTER_DRIVER_INFO_LEVEL ctr
;
4071 /* delete the tdb data first */
4073 get_short_archi(arch
, info_3
->environment
);
4074 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
,
4075 arch
, version
, info_3
->name
);
4077 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4078 key
, delete_files
? "TRUE" : "FALSE" ));
4080 ctr
.info_3
= info_3
;
4081 dump_a_printer_driver( ctr
, 3 );
4084 kbuf
.dsize
=strlen(key
)+1;
4086 /* check if the driver actually exists for this environment */
4088 dbuf
= tdb_fetch( tdb_drivers
, kbuf
);
4090 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key
));
4091 return WERR_UNKNOWN_PRINTER_DRIVER
;
4094 SAFE_FREE( dbuf
.dptr
);
4096 /* ok... the driver exists so the delete should return success */
4098 if (tdb_delete(tdb_drivers
, kbuf
) == -1) {
4099 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key
));
4100 return WERR_ACCESS_DENIED
;
4104 * now delete any associated files if delete_files == True
4105 * even if this part failes, we return succes because the
4106 * driver doesn not exist any more
4110 delete_driver_files( info_3
, user
);
4113 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key
));
4118 /****************************************************************************
4119 Store a security desc for a printer.
4120 ****************************************************************************/
4122 WERROR
nt_printing_setsec(const char *printername
, SEC_DESC_BUF
*secdesc_ctr
)
4124 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4125 SEC_DESC_BUF
*old_secdesc_ctr
= NULL
;
4127 TALLOC_CTX
*mem_ctx
= NULL
;
4131 mem_ctx
= talloc_init();
4132 if (mem_ctx
== NULL
)
4135 /* The old owner and group sids of the security descriptor are not
4136 present when new ACEs are added or removed by changing printer
4137 permissions through NT. If they are NULL in the new security
4138 descriptor then copy them over from the old one. */
4140 if (!secdesc_ctr
->sec
->owner_sid
|| !secdesc_ctr
->sec
->grp_sid
) {
4141 DOM_SID
*owner_sid
, *group_sid
;
4142 SEC_ACL
*dacl
, *sacl
;
4143 SEC_DESC
*psd
= NULL
;
4146 nt_printing_getsec(mem_ctx
, printername
, &old_secdesc_ctr
);
4148 /* Pick out correct owner and group sids */
4150 owner_sid
= secdesc_ctr
->sec
->owner_sid
?
4151 secdesc_ctr
->sec
->owner_sid
:
4152 old_secdesc_ctr
->sec
->owner_sid
;
4154 group_sid
= secdesc_ctr
->sec
->grp_sid
?
4155 secdesc_ctr
->sec
->grp_sid
:
4156 old_secdesc_ctr
->sec
->grp_sid
;
4158 dacl
= secdesc_ctr
->sec
->dacl
?
4159 secdesc_ctr
->sec
->dacl
:
4160 old_secdesc_ctr
->sec
->dacl
;
4162 sacl
= secdesc_ctr
->sec
->sacl
?
4163 secdesc_ctr
->sec
->sacl
:
4164 old_secdesc_ctr
->sec
->sacl
;
4166 /* Make a deep copy of the security descriptor */
4168 psd
= make_sec_desc(mem_ctx
, secdesc_ctr
->sec
->revision
,
4169 owner_sid
, group_sid
,
4174 new_secdesc_ctr
= make_sec_desc_buf(mem_ctx
, size
, psd
);
4177 if (!new_secdesc_ctr
) {
4178 new_secdesc_ctr
= secdesc_ctr
;
4181 /* Store the security descriptor in a tdb */
4183 prs_init(&ps
, (uint32
)sec_desc_size(new_secdesc_ctr
->sec
) +
4184 sizeof(SEC_DESC_BUF
), mem_ctx
, MARSHALL
);
4186 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr
,
4188 status
= WERR_BADFUNC
;
4192 slprintf(key
, sizeof(key
)-1, "SECDESC/%s", printername
);
4194 if (tdb_prs_store(tdb_printers
, key
, &ps
)==0) {
4197 DEBUG(1,("Failed to store secdesc for %s\n", printername
));
4198 status
= WERR_BADFUNC
;
4201 /* Free malloc'ed memory */
4207 talloc_destroy(mem_ctx
);
4211 /****************************************************************************
4212 Construct a default security descriptor buffer for a printer.
4213 ****************************************************************************/
4215 static SEC_DESC_BUF
*construct_default_printer_sdb(TALLOC_CTX
*ctx
)
4219 SEC_ACL
*psa
= NULL
;
4220 SEC_DESC_BUF
*sdb
= NULL
;
4221 SEC_DESC
*psd
= NULL
;
4225 /* Create an ACE where Everyone is allowed to print */
4227 init_sec_access(&sa
, PRINTER_ACE_PRINT
);
4228 init_sec_ace(&ace
[0], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4229 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4231 /* Make the security descriptor owned by the Administrators group
4232 on the PDC of the domain. */
4234 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
4235 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4238 /* Backup plan - make printer owned by admins.
4239 This should emulate a lanman printer as security
4240 settings can't be changed. */
4242 sid_copy(&owner_sid
, get_global_sam_sid());
4243 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4246 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
4247 init_sec_ace(&ace
[1], &owner_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4248 sa
, SEC_ACE_FLAG_OBJECT_INHERIT
|
4249 SEC_ACE_FLAG_INHERIT_ONLY
);
4251 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
4252 init_sec_ace(&ace
[2], &owner_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4253 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4255 /* The ACL revision number in rpc_secdesc.h differs from the one
4256 created by NT when setting ACE entries in printer
4257 descriptors. NT4 complains about the property being edited by a
4260 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, 3, ace
)) != NULL
) {
4261 psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
,
4263 NULL
, psa
, &sd_size
);
4267 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4271 sdb
= make_sec_desc_buf(ctx
, sd_size
, psd
);
4273 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4274 (unsigned int)sd_size
));
4279 /****************************************************************************
4280 Get a security desc for a printer.
4281 ****************************************************************************/
4283 BOOL
nt_printing_getsec(TALLOC_CTX
*ctx
, const char *printername
, SEC_DESC_BUF
**secdesc_ctr
)
4289 if ((temp
= strchr(printername
+ 2, '\\'))) {
4290 printername
= temp
+ 1;
4293 /* Fetch security descriptor from tdb */
4295 slprintf(key
, sizeof(key
)-1, "SECDESC/%s", printername
);
4297 if (tdb_prs_fetch(tdb_printers
, key
, &ps
, ctx
)!=0 ||
4298 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1)) {
4300 DEBUG(4,("using default secdesc for %s\n", printername
));
4302 if (!(*secdesc_ctr
= construct_default_printer_sdb(ctx
))) {
4306 /* Save default security descriptor for later */
4308 prs_init(&ps
, (uint32
)sec_desc_size((*secdesc_ctr
)->sec
) +
4309 sizeof(SEC_DESC_BUF
), ctx
, MARSHALL
);
4311 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1))
4312 tdb_prs_store(tdb_printers
, key
, &ps
);
4319 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4320 this security descriptor has been created when winbindd was
4321 down. Take ownership of security descriptor. */
4323 if (sid_equal((*secdesc_ctr
)->sec
->owner_sid
, &global_sid_World
)) {
4326 /* Change sd owner to workgroup administrator */
4328 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
4329 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4330 SEC_DESC
*psd
= NULL
;
4335 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4337 psd
= make_sec_desc(ctx
, (*secdesc_ctr
)->sec
->revision
,
4339 (*secdesc_ctr
)->sec
->grp_sid
,
4340 (*secdesc_ctr
)->sec
->sacl
,
4341 (*secdesc_ctr
)->sec
->dacl
,
4344 new_secdesc_ctr
= make_sec_desc_buf(ctx
, size
, psd
);
4346 /* Swap with other one */
4348 *secdesc_ctr
= new_secdesc_ctr
;
4352 nt_printing_setsec(printername
, *secdesc_ctr
);
4356 if (DEBUGLEVEL
>= 10) {
4357 SEC_ACL
*the_acl
= (*secdesc_ctr
)->sec
->dacl
;
4360 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4361 printername
, the_acl
->num_aces
));
4363 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4366 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
4368 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str
,
4369 the_acl
->ace
[i
].type
, the_acl
->ace
[i
].flags
,
4370 the_acl
->ace
[i
].info
.mask
));
4380 1: level not implemented
4381 2: file doesn't exist
4382 3: can't allocate memory
4383 4: can't free memory
4384 5: non existant struct
4388 A printer and a printer driver are 2 different things.
4389 NT manages them separatelly, Samba does the same.
4390 Why ? Simply because it's easier and it makes sense !
4392 Now explanation: You have 3 printers behind your samba server,
4393 2 of them are the same make and model (laser A and B). But laser B
4394 has an 3000 sheet feeder and laser A doesn't such an option.
4395 Your third printer is an old dot-matrix model for the accounting :-).
4397 If the /usr/local/samba/lib directory (default dir), you will have
4398 5 files to describe all of this.
4400 3 files for the printers (1 by printer):
4403 NTprinter_accounting
4404 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4405 NTdriver_printer model X
4406 NTdriver_printer model Y
4408 jfm: I should use this comment for the text file to explain
4409 same thing for the forms BTW.
4410 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4414 /* Convert generic access rights to printer object specific access rights.
4415 It turns out that NT4 security descriptors use generic access rights and
4416 NT5 the object specific ones. */
4418 void map_printer_permissions(SEC_DESC
*sd
)
4422 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
4423 se_map_generic(&sd
->dacl
->ace
[i
].info
.mask
,
4424 &printer_generic_mapping
);
4428 /****************************************************************************
4429 Check a user has permissions to perform the given operation. We use the
4430 permission constants defined in include/rpc_spoolss.h to check the various
4431 actions we perform when checking printer access.
4433 PRINTER_ACCESS_ADMINISTER:
4434 print_queue_pause, print_queue_resume, update_printer_sec,
4435 update_printer, spoolss_addprinterex_level_2,
4436 _spoolss_setprinterdata
4441 JOB_ACCESS_ADMINISTER:
4442 print_job_delete, print_job_pause, print_job_resume,
4445 ****************************************************************************/
4446 BOOL
print_access_check(struct current_user
*user
, int snum
, int access_type
)
4448 SEC_DESC_BUF
*secdesc
= NULL
;
4449 uint32 access_granted
;
4453 TALLOC_CTX
*mem_ctx
= NULL
;
4454 extern struct current_user current_user
;
4456 /* If user is NULL then use the current_user structure */
4459 user
= ¤t_user
;
4461 /* Always allow root or printer admins to do anything */
4463 if (user
->uid
== 0 ||
4464 user_in_list(uidtoname(user
->uid
), lp_printer_admin(snum
))) {
4468 /* Get printer name */
4470 pname
= PRINTERNAME(snum
);
4472 if (!pname
|| !*pname
) {
4477 /* Get printer security descriptor */
4479 if(!(mem_ctx
= talloc_init())) {
4484 nt_printing_getsec(mem_ctx
, pname
, &secdesc
);
4486 if (access_type
== JOB_ACCESS_ADMINISTER
) {
4487 SEC_DESC_BUF
*parent_secdesc
= secdesc
;
4489 /* Create a child security descriptor to check permissions
4490 against. This is because print jobs are child objects
4491 objects of a printer. */
4493 secdesc
= se_create_child_secdesc(mem_ctx
, parent_secdesc
->sec
, False
);
4495 /* Now this is the bit that really confuses me. The access
4496 type needs to be changed from JOB_ACCESS_ADMINISTER to
4497 PRINTER_ACCESS_ADMINISTER for this to work. Something
4498 to do with the child (job) object becoming like a
4501 access_type
= PRINTER_ACCESS_ADMINISTER
;
4506 map_printer_permissions(secdesc
->sec
);
4508 result
= se_access_check(secdesc
->sec
, user
->nt_user_token
, access_type
,
4509 &access_granted
, &status
);
4511 DEBUG(4, ("access check was %s\n", result
? "SUCCESS" : "FAILURE"));
4513 talloc_destroy(mem_ctx
);
4521 /****************************************************************************
4522 Check the time parameters allow a print operation.
4523 *****************************************************************************/
4525 BOOL
print_time_access_check(int snum
)
4527 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4529 time_t now
= time(NULL
);
4533 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4536 if (printer
->info_2
->starttime
== 0 && printer
->info_2
->untiltime
== 0)
4540 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
4542 if (mins
>= printer
->info_2
->starttime
&& mins
<= printer
->info_2
->untiltime
)
4545 free_a_printer(&printer
, 2);