2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
6 * Copyright (C) Gerald Carter 2002-2003.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 extern DOM_SID global_sid_World
;
27 static TDB_CONTEXT
*tdb_forms
; /* used for forms files */
28 static TDB_CONTEXT
*tdb_drivers
; /* used for driver files */
29 static TDB_CONTEXT
*tdb_printers
; /* used for printers files */
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
42 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
44 /* Map generic permissions to printer object specific permissions */
46 GENERIC_MAPPING printer_generic_mapping
= {
53 STANDARD_MAPPING printer_std_mapping
= {
60 /* Map generic permissions to print server object specific permissions */
62 GENERIC_MAPPING printserver_generic_mapping
= {
69 STANDARD_MAPPING printserver_std_mapping
= {
76 /* We need one default form to support our default printer. Msoft adds the
77 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
78 array index). Letter is always first, so (for the current code) additions
79 always put things in the correct order. */
80 static const nt_forms_struct default_forms
[] = {
81 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
84 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
85 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
86 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
87 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
88 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
89 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
92 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
93 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
94 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
95 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
96 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
97 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
98 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
99 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
100 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
101 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
102 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
103 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
104 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
105 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
106 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
107 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
108 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
109 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
110 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
111 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
112 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
113 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
114 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
115 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
116 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
117 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
118 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
119 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
120 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
121 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
122 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
123 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
124 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
125 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
126 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
127 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
128 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
131 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
132 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
133 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
134 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
135 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
136 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
138 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
139 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
140 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
141 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
142 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
143 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
144 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
145 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
146 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
147 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
148 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
149 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
150 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
151 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
152 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
153 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
154 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
155 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
156 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
157 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
158 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
159 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
160 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
161 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
162 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
163 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
164 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
165 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
166 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
167 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
168 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
169 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
170 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
171 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
172 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
173 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
174 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
175 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
176 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
177 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
178 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
179 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
180 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
181 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
182 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
183 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
184 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
185 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
186 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
187 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
188 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
189 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
190 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
191 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
192 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
193 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
194 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
195 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
196 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
197 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
198 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
202 const char *long_archi
;
203 const char *short_archi
;
207 #define SPL_ARCH_WIN40 "WIN40"
208 #define SPL_ARCH_W32X86 "W32X86"
209 #define SPL_ARCH_W32MIPS "W32MIPS"
210 #define SPL_ARCH_W32ALPHA "W32ALPHA"
211 #define SPL_ARCH_W32PPC "W32PPC"
213 static const struct table_node archi_table
[]= {
215 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
216 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
217 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
218 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
219 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
223 static BOOL
upgrade_to_version_3(void)
225 TDB_DATA kbuf
, newkey
, dbuf
;
227 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
229 for (kbuf
= tdb_firstkey(tdb_drivers
); kbuf
.dptr
;
230 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
232 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
234 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) == 0) {
235 DEBUG(0,("upgrade_to_version_3:moving form\n"));
236 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
237 SAFE_FREE(dbuf
.dptr
);
238 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms
)));
241 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
242 SAFE_FREE(dbuf
.dptr
);
243 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
248 if (strncmp(kbuf
.dptr
, PRINTERS_PREFIX
, strlen(PRINTERS_PREFIX
)) == 0) {
249 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
250 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
251 SAFE_FREE(dbuf
.dptr
);
252 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers
)));
255 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
256 SAFE_FREE(dbuf
.dptr
);
257 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
262 if (strncmp(kbuf
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
)) == 0) {
263 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
264 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
265 SAFE_FREE(dbuf
.dptr
);
266 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers
)));
269 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
270 SAFE_FREE(dbuf
.dptr
);
271 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
276 SAFE_FREE(dbuf
.dptr
);
282 /****************************************************************************
283 Open the NT printing tdbs. Done once before fork().
284 ****************************************************************************/
286 BOOL
nt_printing_init(void)
288 static pid_t local_pid
;
289 const char *vstring
= "INFO/version";
291 if (tdb_drivers
&& tdb_printers
&& tdb_forms
&& local_pid
== sys_getpid())
295 tdb_close(tdb_drivers
);
296 tdb_drivers
= tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
298 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
299 lock_path("ntdrivers.tdb"), strerror(errno
) ));
304 tdb_close(tdb_printers
);
305 tdb_printers
= tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
307 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
308 lock_path("ntprinters.tdb"), strerror(errno
) ));
313 tdb_close(tdb_forms
);
314 tdb_forms
= tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
316 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
317 lock_path("ntforms.tdb"), strerror(errno
) ));
321 local_pid
= sys_getpid();
323 /* handle a Samba upgrade */
324 tdb_lock_bystring(tdb_drivers
, vstring
, 0);
328 /* Cope with byte-reversed older versions of the db. */
329 vers_id
= tdb_fetch_int32(tdb_drivers
, vstring
);
330 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_2
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_2
)) {
331 /* Written on a bigendian machine with old fetch_int code. Save as le. */
332 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
333 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION
);
334 vers_id
= NTDRIVERS_DATABASE_VERSION
;
337 if (vers_id
!= NTDRIVERS_DATABASE_VERSION
) {
339 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_1
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_1
)) {
340 if (!upgrade_to_version_3())
343 tdb_traverse(tdb_drivers
, tdb_traverse_delete_fn
, NULL
);
345 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION
);
348 tdb_unlock_bystring(tdb_drivers
, vstring
);
350 update_c_setprinter(True
);
353 * register callback to handle updating printers as new
354 * drivers are installed
357 message_register( MSG_PRINTER_DRVUPGRADE
, do_drv_upgrade_printer
);
360 * register callback to handle updating printer data
361 * when a driver is initialized
364 message_register( MSG_PRINTERDATA_INIT_RESET
, reset_all_printerdata
);
370 /*******************************************************************
371 tdb traversal function for counting printers.
372 ********************************************************************/
374 static int traverse_counting_printers(TDB_CONTEXT
*t
, TDB_DATA key
,
375 TDB_DATA data
, void *context
)
377 int *printer_count
= (int*)context
;
379 if (memcmp(PRINTERS_PREFIX
, key
.dptr
, sizeof(PRINTERS_PREFIX
)-1) == 0) {
381 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key
.dptr
, *printer_count
));
387 /*******************************************************************
388 Update the spooler global c_setprinter. This variable is initialized
389 when the parent smbd starts with the number of existing printers. It
390 is monotonically increased by the current number of printers *after*
391 each add or delete printer RPC. Only Microsoft knows why... JRR020119
392 ********************************************************************/
394 uint32
update_c_setprinter(BOOL initialize
)
397 int32 printer_count
= 0;
399 tdb_lock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
, 0);
401 /* Traverse the tdb, counting the printers */
402 tdb_traverse(tdb_printers
, traverse_counting_printers
, (void *)&printer_count
);
404 /* If initializing, set c_setprinter to current printers count
405 * otherwise, bump it by the current printer count
408 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
) + printer_count
;
410 c_setprinter
= printer_count
;
412 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter
));
413 tdb_store_int32(tdb_printers
, GLOBAL_C_SETPRINTER
, c_setprinter
);
415 tdb_unlock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
417 return (uint32
)c_setprinter
;
420 /*******************************************************************
421 Get the spooler global c_setprinter, accounting for initialization.
422 ********************************************************************/
424 uint32
get_c_setprinter(void)
426 int32 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
);
428 if (c_setprinter
== (int32
)-1)
429 c_setprinter
= update_c_setprinter(True
);
431 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter
));
433 return (uint32
)c_setprinter
;
436 /****************************************************************************
437 Get builtin form struct list.
438 ****************************************************************************/
440 int get_builtin_ntforms(nt_forms_struct
**list
)
442 *list
= (nt_forms_struct
*)memdup(&default_forms
[0], sizeof(default_forms
));
443 return sizeof(default_forms
) / sizeof(default_forms
[0]);
446 /****************************************************************************
447 get a builtin form struct
448 ****************************************************************************/
450 BOOL
get_a_builtin_ntform(UNISTR2
*uni_formname
,nt_forms_struct
*form
)
454 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
455 DEBUGADD(6,("Looking for builtin form %s \n", form_name
));
456 count
= sizeof(default_forms
) / sizeof(default_forms
[0]);
457 for (i
=0;i
<count
;i
++) {
458 if (strequal(form_name
,default_forms
[i
].name
)) {
459 DEBUGADD(6,("Found builtin form %s \n", form_name
));
460 memcpy(form
,&default_forms
[i
],sizeof(*form
));
468 /****************************************************************************
469 get a form struct list
470 ****************************************************************************/
471 int get_ntforms(nt_forms_struct
**list
)
473 TDB_DATA kbuf
, newkey
, dbuf
;
475 nt_forms_struct form
;
480 for (kbuf
= tdb_firstkey(tdb_forms
);
482 newkey
= tdb_nextkey(tdb_forms
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
)
484 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) != 0)
487 dbuf
= tdb_fetch(tdb_forms
, kbuf
);
491 fstrcpy(form
.name
, kbuf
.dptr
+strlen(FORMS_PREFIX
));
492 ret
= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dddddddd",
493 &i
, &form
.flag
, &form
.width
, &form
.length
, &form
.left
,
494 &form
.top
, &form
.right
, &form
.bottom
);
495 SAFE_FREE(dbuf
.dptr
);
496 if (ret
!= dbuf
.dsize
)
499 tl
= Realloc(*list
, sizeof(nt_forms_struct
)*(n
+1));
501 DEBUG(0,("get_ntforms: Realloc fail.\n"));
513 /****************************************************************************
514 write a form struct list
515 ****************************************************************************/
516 int write_ntforms(nt_forms_struct
**list
, int number
)
523 for (i
=0;i
<number
;i
++) {
524 /* save index, so list is rebuilt in correct order */
525 len
= tdb_pack(buf
, sizeof(buf
), "dddddddd",
526 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
527 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
529 if (len
> sizeof(buf
)) break;
530 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[i
].name
);
531 kbuf
.dsize
= strlen(key
)+1;
535 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) break;
541 /****************************************************************************
542 add a form struct at the end of the list
543 ****************************************************************************/
544 BOOL
add_a_form(nt_forms_struct
**list
, const FORM
*form
, int *count
)
552 * NT tries to add forms even when
553 * they are already in the base
554 * only update the values if already present
559 unistr2_to_ascii(form_name
, &form
->name
, sizeof(form_name
)-1);
560 for (n
=0; n
<*count
; n
++) {
561 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
562 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name
));
569 if((tl
=Realloc(*list
, (n
+1)*sizeof(nt_forms_struct
))) == NULL
) {
570 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
574 unistr2_to_ascii((*list
)[n
].name
, &form
->name
, sizeof((*list
)[n
].name
)-1);
578 (*list
)[n
].flag
=form
->flags
;
579 (*list
)[n
].width
=form
->size_x
;
580 (*list
)[n
].length
=form
->size_y
;
581 (*list
)[n
].left
=form
->left
;
582 (*list
)[n
].top
=form
->top
;
583 (*list
)[n
].right
=form
->right
;
584 (*list
)[n
].bottom
=form
->bottom
;
589 /****************************************************************************
590 Delete a named form struct.
591 ****************************************************************************/
593 BOOL
delete_a_form(nt_forms_struct
**list
, UNISTR2
*del_name
, int *count
, WERROR
*ret
)
602 unistr2_to_ascii(form_name
, del_name
, sizeof(form_name
)-1);
604 for (n
=0; n
<*count
; n
++) {
605 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
606 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name
));
612 DEBUG(10,("delete_a_form, [%s] not found\n", form_name
));
613 *ret
= WERR_INVALID_PARAM
;
617 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[n
].name
);
618 kbuf
.dsize
= strlen(key
)+1;
620 if (tdb_delete(tdb_forms
, kbuf
) != 0) {
628 /****************************************************************************
629 Update a form struct.
630 ****************************************************************************/
632 void update_a_form(nt_forms_struct
**list
, const FORM
*form
, int count
)
636 unistr2_to_ascii(form_name
, &(form
->name
), sizeof(form_name
)-1);
638 DEBUG(106, ("[%s]\n", form_name
));
639 for (n
=0; n
<count
; n
++) {
640 DEBUGADD(106, ("n [%d]:[%s]\n", n
, (*list
)[n
].name
));
641 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
)))
645 if (n
==count
) return;
647 (*list
)[n
].flag
=form
->flags
;
648 (*list
)[n
].width
=form
->size_x
;
649 (*list
)[n
].length
=form
->size_y
;
650 (*list
)[n
].left
=form
->left
;
651 (*list
)[n
].top
=form
->top
;
652 (*list
)[n
].right
=form
->right
;
653 (*list
)[n
].bottom
=form
->bottom
;
656 /****************************************************************************
657 Get the nt drivers list.
658 Traverse the database and look-up the matching names.
659 ****************************************************************************/
660 int get_ntdrivers(fstring
**list
, const char *architecture
, uint32 version
)
663 const char *short_archi
;
666 TDB_DATA kbuf
, newkey
;
668 short_archi
= get_short_archi(architecture
);
669 slprintf(key
, sizeof(key
)-1, "%s%s/%d/", DRIVERS_PREFIX
, short_archi
, version
);
671 for (kbuf
= tdb_firstkey(tdb_drivers
);
673 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
675 if (strncmp(kbuf
.dptr
, key
, strlen(key
)) != 0)
678 if((fl
= Realloc(*list
, sizeof(fstring
)*(total
+1))) == NULL
) {
679 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
684 fstrcpy((*list
)[total
], kbuf
.dptr
+strlen(key
));
691 /****************************************************************************
692 function to do the mapping between the long architecture name and
694 ****************************************************************************/
695 const char *get_short_archi(const char *long_archi
)
699 DEBUG(107,("Getting architecture dependant directory\n"));
702 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
703 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
705 if (archi_table
[i
].long_archi
==NULL
) {
706 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
710 /* this might be client code - but shouldn't this be an fstrcpy etc? */
713 DEBUGADD(108,("index: [%d]\n", i
));
714 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
715 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
717 return archi_table
[i
].short_archi
;
720 /****************************************************************************
721 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
722 There are two case to be covered here: PE (Portable Executable) and NE (New
723 Executable) files. Both files support the same INFO structure, but PE files
724 store the signature in unicode, and NE files store it as !unicode.
725 returns -1 on error, 1 on version info found, and 0 on no version info found.
726 ****************************************************************************/
728 static int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
734 if ((buf
=malloc(PE_HEADER_SIZE
)) == NULL
) {
735 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
736 fname
, PE_HEADER_SIZE
));
740 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
741 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
742 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
744 goto no_version_info
;
747 /* Is this really a DOS header? */
748 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
749 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
750 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
751 goto no_version_info
;
754 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
755 if (SMB_VFS_LSEEK(fsp
, fsp
->fd
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
756 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
758 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
759 goto no_version_info
;
762 if ((byte_count
= vfs_read_data(fsp
, buf
, PE_HEADER_SIZE
)) < PE_HEADER_SIZE
) {
763 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
765 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
766 goto no_version_info
;
769 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
770 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
772 int section_table_bytes
;
774 if (SVAL(buf
,PE_HEADER_MACHINE_OFFSET
) != PE_HEADER_MACHINE_I386
) {
775 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
776 fname
, SVAL(buf
,PE_HEADER_MACHINE_OFFSET
)));
777 /* At this point, we assume the file is in error. It still could be somthing
778 * else besides a PE file, but it unlikely at this point.
783 /* get the section table */
784 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
785 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
787 if ((buf
=malloc(section_table_bytes
)) == NULL
) {
788 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
789 fname
, section_table_bytes
));
793 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
794 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
799 /* Iterate the section table looking for the resource section ".rsrc" */
800 for (i
= 0; i
< num_sections
; i
++) {
801 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
803 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
804 int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
805 int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
808 if ((buf
=malloc(section_bytes
)) == NULL
) {
809 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
810 fname
, section_bytes
));
814 /* Seek to the start of the .rsrc section info */
815 if (SMB_VFS_LSEEK(fsp
, fsp
->fd
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
816 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
821 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
822 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
827 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
828 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
829 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
830 /* Align to next long address */
831 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
833 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
834 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
835 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
837 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
838 fname
, *major
, *minor
,
839 (*major
>>16)&0xffff, *major
&0xffff,
840 (*minor
>>16)&0xffff, *minor
&0xffff));
849 /* Version info not found, fall back to origin date/time */
850 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
854 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
855 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
856 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
857 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
858 /* At this point, we assume the file is in error. It still could be somthing
859 * else besides a NE file, but it unlikely at this point. */
863 /* Allocate a bit more space to speed up things */
865 if ((buf
=malloc(VS_NE_BUF_SIZE
)) == NULL
) {
866 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
867 fname
, PE_HEADER_SIZE
));
871 /* This is a HACK! I got tired of trying to sort through the messy
872 * 'NE' file format. If anyone wants to clean this up please have at
873 * it, but this works. 'NE' files will eventually fade away. JRR */
874 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
875 /* Cover case that should not occur in a well formed 'NE' .dll file */
876 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
878 for(i
=0; i
<byte_count
; i
++) {
879 /* Fast skip past data that can't possibly match */
880 if (buf
[i
] != 'V') continue;
882 /* Potential match data crosses buf boundry, move it to beginning
883 * of buf, and fill the buf with as much as it will hold. */
884 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
887 memcpy(buf
, &buf
[i
], byte_count
-i
);
888 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
889 (byte_count
-i
))) < 0) {
891 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
896 byte_count
= bc
+ (byte_count
- i
);
897 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
902 /* Check that the full signature string and the magic number that
903 * follows exist (not a perfect solution, but the chances that this
904 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
905 * twice, as it is simpler to read the code. */
906 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
907 /* Compute skip alignment to next long address */
908 int skip
= -(SMB_VFS_LSEEK(fsp
, fsp
->fd
, 0, SEEK_CUR
) - (byte_count
- i
) +
909 sizeof(VS_SIGNATURE
)) & 3;
910 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
912 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
913 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
914 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
915 fname
, *major
, *minor
,
916 (*major
>>16)&0xffff, *major
&0xffff,
917 (*minor
>>16)&0xffff, *minor
&0xffff));
924 /* Version info not found, fall back to origin date/time */
925 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
930 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
931 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
932 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
943 /****************************************************************************
944 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
945 share one or more files. During the MS installation process files are checked
946 to insure that only a newer version of a shared file is installed over an
947 older version. There are several possibilities for this comparison. If there
948 is no previous version, the new one is newer (obviously). If either file is
949 missing the version info structure, compare the creation date (on Unix use
950 the modification date). Otherwise chose the numerically larger version number.
951 ****************************************************************************/
953 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
955 BOOL use_version
= True
;
960 time_t new_create_time
;
964 time_t old_create_time
;
968 files_struct
*fsp
= NULL
;
970 SMB_STRUCT_STAT stat_buf
;
974 ZERO_STRUCT(stat_buf
);
975 new_create_time
= (time_t)0;
976 old_create_time
= (time_t)0;
978 /* Get file version info (if available) for previous file (if it exists) */
979 pstrcpy(filepath
, old_file
);
981 unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
983 fsp
= open_file_shared(conn
, filepath
, &stat_buf
,
984 SET_OPEN_MODE(DOS_OPEN_RDONLY
),
985 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
986 0, 0, &access_mode
, &action
);
988 /* Old file not found, so by definition new file is in fact newer */
989 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
994 int ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
995 if (ret
== -1) goto error_exit
;
998 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1000 use_version
= False
;
1001 if (SMB_VFS_FSTAT(fsp
, fsp
->fd
, &st
) == -1) goto error_exit
;
1002 old_create_time
= st
.st_mtime
;
1003 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time
));
1006 close_file(fsp
, True
);
1008 /* Get file version info (if available) for new file */
1009 pstrcpy(filepath
, new_file
);
1010 unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1012 fsp
= open_file_shared(conn
, filepath
, &stat_buf
,
1013 SET_OPEN_MODE(DOS_OPEN_RDONLY
),
1014 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1015 0, 0, &access_mode
, &action
);
1017 /* New file not found, this shouldn't occur if the caller did its job */
1018 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1023 int ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
1024 if (ret
== -1) goto error_exit
;
1027 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1029 use_version
= False
;
1030 if (SMB_VFS_FSTAT(fsp
, fsp
->fd
, &st
) == -1) goto error_exit
;
1031 new_create_time
= st
.st_mtime
;
1032 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time
));
1035 close_file(fsp
, True
);
1037 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
1038 /* Compare versions and choose the larger version number */
1039 if (new_major
> old_major
||
1040 (new_major
== old_major
&& new_minor
> old_minor
)) {
1042 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1046 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1051 /* Compare modification time/dates and choose the newest time/date */
1052 if (new_create_time
> old_create_time
) {
1053 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1057 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1064 close_file(fsp
, True
);
1068 /****************************************************************************
1069 Determine the correct cVersion associated with an architecture and driver
1070 ****************************************************************************/
1071 static uint32
get_correct_cversion(const char *architecture
, fstring driverpath_in
,
1072 struct current_user
*user
, WERROR
*perr
)
1081 files_struct
*fsp
= NULL
;
1084 connection_struct
*conn
;
1088 *perr
= WERR_INVALID_PARAM
;
1090 /* If architecture is Windows 95/98/ME, the version is always 0. */
1091 if (strcmp(architecture
, "WIN40") == 0) {
1092 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1098 * Connect to the print$ share under the same account as the user connected
1099 * to the rpc pipe. Note we must still be root to do this.
1102 /* Null password is ok - we are already an authenticated user... */
1103 null_pw
= data_blob(NULL
, 0);
1104 fstrcpy(res_type
, "A:");
1106 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1110 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1111 *perr
= ntstatus_to_werror(nt_status
);
1115 /* We are temporarily becoming the connection user. */
1116 if (!become_user(conn
, user
->vuid
)) {
1117 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1118 *perr
= WERR_ACCESS_DENIED
;
1122 /* Open the driver file (Portable Executable format) and determine the
1123 * deriver the cversion. */
1124 slprintf(driverpath
, sizeof(driverpath
)-1, "%s/%s", architecture
, driverpath_in
);
1126 unix_convert(driverpath
,conn
,NULL
,&bad_path
,&st
);
1128 fsp
= open_file_shared(conn
, driverpath
, &st
,
1129 SET_OPEN_MODE(DOS_OPEN_RDONLY
),
1130 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1131 0, 0, &access_mode
, &action
);
1133 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1134 driverpath
, errno
));
1135 *perr
= WERR_ACCESS_DENIED
;
1141 int ret
= get_file_version(fsp
, driverpath
, &major
, &minor
);
1142 if (ret
== -1) goto error_exit
;
1145 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath
));
1150 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1151 * for more details. Version in this case is not just the version of the
1152 * file, but the version in the sense of kernal mode (2) vs. user mode
1153 * (3) drivers. Other bits of the version fields are the version info.
1156 cversion
= major
& 0x0000ffff;
1158 case 2: /* WinNT drivers */
1159 case 3: /* Win2K drivers */
1163 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1164 driverpath
, cversion
));
1168 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1169 driverpath
, major
, minor
));
1172 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1173 driverpath
, cversion
));
1175 close_file(fsp
, True
);
1176 close_cnum(conn
, user
->vuid
);
1185 close_file(fsp
, True
);
1187 close_cnum(conn
, user
->vuid
);
1192 /****************************************************************************
1193 ****************************************************************************/
1194 static WERROR
clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
,
1195 struct current_user
*user
)
1197 const char *architecture
;
1203 /* clean up the driver name.
1204 * we can get .\driver.dll
1205 * or worse c:\windows\system\driver.dll !
1207 /* using an intermediate string to not have overlaping memcpy()'s */
1208 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1209 fstrcpy(new_name
, p
+1);
1210 fstrcpy(driver
->driverpath
, new_name
);
1213 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1214 fstrcpy(new_name
, p
+1);
1215 fstrcpy(driver
->datafile
, new_name
);
1218 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1219 fstrcpy(new_name
, p
+1);
1220 fstrcpy(driver
->configfile
, new_name
);
1223 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1224 fstrcpy(new_name
, p
+1);
1225 fstrcpy(driver
->helpfile
, new_name
);
1228 if (driver
->dependentfiles
) {
1229 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1230 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1231 fstrcpy(new_name
, p
+1);
1232 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1237 architecture
= get_short_archi(driver
->environment
);
1239 /* jfm:7/16/2000 the client always sends the cversion=0.
1240 * The server should check which version the driver is by reading
1241 * the PE header of driver->driverpath.
1243 * For Windows 95/98 the version is 0 (so the value sent is correct)
1244 * For Windows NT (the architecture doesn't matter)
1245 * NT 3.1: cversion=0
1246 * NT 3.5/3.51: cversion=1
1250 if ((driver
->cversion
= get_correct_cversion( architecture
,
1251 driver
->driverpath
, user
, &err
)) == -1)
1257 /****************************************************************************
1258 ****************************************************************************/
1259 static WERROR
clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
, struct current_user
*user
)
1261 const char *architecture
;
1267 /* clean up the driver name.
1268 * we can get .\driver.dll
1269 * or worse c:\windows\system\driver.dll !
1271 /* using an intermediate string to not have overlaping memcpy()'s */
1272 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1273 fstrcpy(new_name
, p
+1);
1274 fstrcpy(driver
->driverpath
, new_name
);
1277 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1278 fstrcpy(new_name
, p
+1);
1279 fstrcpy(driver
->datafile
, new_name
);
1282 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1283 fstrcpy(new_name
, p
+1);
1284 fstrcpy(driver
->configfile
, new_name
);
1287 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1288 fstrcpy(new_name
, p
+1);
1289 fstrcpy(driver
->helpfile
, new_name
);
1292 if (driver
->dependentfiles
) {
1293 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1294 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1295 fstrcpy(new_name
, p
+1);
1296 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1301 architecture
= get_short_archi(driver
->environment
);
1303 /* jfm:7/16/2000 the client always sends the cversion=0.
1304 * The server should check which version the driver is by reading
1305 * the PE header of driver->driverpath.
1307 * For Windows 95/98 the version is 0 (so the value sent is correct)
1308 * For Windows NT (the architecture doesn't matter)
1309 * NT 3.1: cversion=0
1310 * NT 3.5/3.51: cversion=1
1314 if ((driver
->version
= get_correct_cversion(architecture
, driver
->driverpath
, user
, &err
)) == -1)
1320 /****************************************************************************
1321 ****************************************************************************/
1322 WERROR
clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
,
1323 uint32 level
, struct current_user
*user
)
1328 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1329 driver
=driver_abstract
.info_3
;
1330 return clean_up_driver_struct_level_3(driver
, user
);
1334 NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
;
1335 driver
=driver_abstract
.info_6
;
1336 return clean_up_driver_struct_level_6(driver
, user
);
1339 return WERR_INVALID_PARAM
;
1343 /****************************************************************************
1344 This function sucks and should be replaced. JRA.
1345 ****************************************************************************/
1347 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*dst
, NT_PRINTER_DRIVER_INFO_LEVEL_6
*src
)
1349 dst
->cversion
= src
->version
;
1351 fstrcpy( dst
->name
, src
->name
);
1352 fstrcpy( dst
->environment
, src
->environment
);
1353 fstrcpy( dst
->driverpath
, src
->driverpath
);
1354 fstrcpy( dst
->datafile
, src
->datafile
);
1355 fstrcpy( dst
->configfile
, src
->configfile
);
1356 fstrcpy( dst
->helpfile
, src
->helpfile
);
1357 fstrcpy( dst
->monitorname
, src
->monitorname
);
1358 fstrcpy( dst
->defaultdatatype
, src
->defaultdatatype
);
1359 dst
->dependentfiles
= src
->dependentfiles
;
1362 #if 0 /* Debugging function */
1364 static char* ffmt(unsigned char *c
){
1366 static char ffmt_str
[17];
1368 for (i
=0; i
<16; i
++) {
1369 if ((c
[i
] < ' ') || (c
[i
] > '~'))
1380 /****************************************************************************
1381 ****************************************************************************/
1382 BOOL
move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
, uint32 level
,
1383 struct current_user
*user
, WERROR
*perr
)
1385 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1386 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver
;
1387 const char *architecture
;
1392 connection_struct
*conn
;
1400 memset(inbuf
, '\0', sizeof(inbuf
));
1401 memset(outbuf
, '\0', sizeof(outbuf
));
1405 driver
=driver_abstract
.info_3
;
1406 else if (level
==6) {
1407 convert_level_6_to_level3(&converted_driver
, driver_abstract
.info_6
);
1408 driver
= &converted_driver
;
1410 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level
));
1414 architecture
= get_short_archi(driver
->environment
);
1417 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1418 * Note we must be root to do this.
1421 null_pw
= data_blob(NULL
, 0);
1422 fstrcpy(res_type
, "A:");
1424 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1428 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1429 *perr
= ntstatus_to_werror(nt_status
);
1434 * Save who we are - we are temporarily becoming the connection user.
1437 if (!become_user(conn
, conn
->vuid
)) {
1438 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1443 * make the directories version and version\driver_name
1444 * under the architecture directory.
1446 DEBUG(5,("Creating first directory\n"));
1447 slprintf(new_dir
, sizeof(new_dir
)-1, "%s/%d", architecture
, driver
->cversion
);
1448 mkdir_internal(conn
, new_dir
);
1450 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1451 * listed for this driver which has already been moved, skip it (note:
1452 * drivers may list the same file name several times. Then check if the
1453 * file already exists in archi\cversion\, if so, check that the version
1454 * info (or time stamps if version info is unavailable) is newer (or the
1455 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1456 * Otherwise, delete the file.
1458 * If a file is not moved to archi\cversion\ because of an error, all the
1459 * rest of the 'unmoved' driver files are removed from archi\. If one or
1460 * more of the driver's files was already moved to archi\cversion\, it
1461 * potentially leaves the driver in a partially updated state. Version
1462 * trauma will most likely occur if an client attempts to use any printer
1463 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1464 * done is appropriate... later JRR
1467 DEBUG(5,("Moving files now !\n"));
1469 if (driver
->driverpath
&& strlen(driver
->driverpath
)) {
1470 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->driverpath
);
1471 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->driverpath
);
1472 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1474 status
= rename_internals(conn
, new_name
, old_name
, True
);
1475 if (!NT_STATUS_IS_OK(status
)) {
1476 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1477 new_name
, old_name
));
1478 *perr
= ntstatus_to_werror(status
);
1479 unlink_internals(conn
, 0, new_name
);
1484 unlink_internals(conn
, 0, new_name
);
1487 if (driver
->datafile
&& strlen(driver
->datafile
)) {
1488 if (!strequal(driver
->datafile
, driver
->driverpath
)) {
1489 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->datafile
);
1490 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->datafile
);
1491 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1493 status
= rename_internals(conn
, new_name
, old_name
, True
);
1494 if (!NT_STATUS_IS_OK(status
)) {
1495 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1496 new_name
, old_name
));
1497 *perr
= ntstatus_to_werror(status
);
1498 unlink_internals(conn
, 0, new_name
);
1503 unlink_internals(conn
, 0, new_name
);
1507 if (driver
->configfile
&& strlen(driver
->configfile
)) {
1508 if (!strequal(driver
->configfile
, driver
->driverpath
) &&
1509 !strequal(driver
->configfile
, driver
->datafile
)) {
1510 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->configfile
);
1511 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->configfile
);
1512 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1514 status
= rename_internals(conn
, new_name
, old_name
, True
);
1515 if (!NT_STATUS_IS_OK(status
)) {
1516 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1517 new_name
, old_name
));
1518 *perr
= ntstatus_to_werror(status
);
1519 unlink_internals(conn
, 0, new_name
);
1524 unlink_internals(conn
, 0, new_name
);
1528 if (driver
->helpfile
&& strlen(driver
->helpfile
)) {
1529 if (!strequal(driver
->helpfile
, driver
->driverpath
) &&
1530 !strequal(driver
->helpfile
, driver
->datafile
) &&
1531 !strequal(driver
->helpfile
, driver
->configfile
)) {
1532 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->helpfile
);
1533 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->helpfile
);
1534 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1536 status
= rename_internals(conn
, new_name
, old_name
, True
);
1537 if (!NT_STATUS_IS_OK(status
)) {
1538 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1539 new_name
, old_name
));
1540 *perr
= ntstatus_to_werror(status
);
1541 unlink_internals(conn
, 0, new_name
);
1546 unlink_internals(conn
, 0, new_name
);
1550 if (driver
->dependentfiles
) {
1551 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1552 if (!strequal(driver
->dependentfiles
[i
], driver
->driverpath
) &&
1553 !strequal(driver
->dependentfiles
[i
], driver
->datafile
) &&
1554 !strequal(driver
->dependentfiles
[i
], driver
->configfile
) &&
1555 !strequal(driver
->dependentfiles
[i
], driver
->helpfile
)) {
1557 for (j
=0; j
< i
; j
++) {
1558 if (strequal(driver
->dependentfiles
[i
], driver
->dependentfiles
[j
])) {
1563 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->dependentfiles
[i
]);
1564 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->dependentfiles
[i
]);
1565 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1567 status
= rename_internals(conn
, new_name
, old_name
, True
);
1568 if (!NT_STATUS_IS_OK(status
)) {
1569 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1570 new_name
, old_name
));
1571 *perr
= ntstatus_to_werror(status
);
1572 unlink_internals(conn
, 0, new_name
);
1577 unlink_internals(conn
, 0, new_name
);
1583 close_cnum(conn
, user
->vuid
);
1586 return ver
== -1 ? False
: True
;
1589 /****************************************************************************
1590 ****************************************************************************/
1591 static uint32
add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
)
1594 const char *architecture
;
1600 TDB_DATA kbuf
, dbuf
;
1602 architecture
= get_short_archi(driver
->environment
);
1604 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1605 * \\server is added in the rpc server layer.
1606 * It does make sense to NOT store the server's name in the printer TDB.
1609 slprintf(directory
, sizeof(directory
)-1, "\\print$\\%s\\%d\\", architecture
, driver
->cversion
);
1611 /* .inf files do not always list a file for each of the four standard files.
1612 * Don't prepend a path to a null filename, or client claims:
1613 * "The server on which the printer resides does not have a suitable
1614 * <printer driver name> printer driver installed. Click OK if you
1615 * wish to install the driver on your local machine."
1617 if (strlen(driver
->driverpath
)) {
1618 fstrcpy(temp_name
, driver
->driverpath
);
1619 slprintf(driver
->driverpath
, sizeof(driver
->driverpath
)-1, "%s%s", directory
, temp_name
);
1622 if (strlen(driver
->datafile
)) {
1623 fstrcpy(temp_name
, driver
->datafile
);
1624 slprintf(driver
->datafile
, sizeof(driver
->datafile
)-1, "%s%s", directory
, temp_name
);
1627 if (strlen(driver
->configfile
)) {
1628 fstrcpy(temp_name
, driver
->configfile
);
1629 slprintf(driver
->configfile
, sizeof(driver
->configfile
)-1, "%s%s", directory
, temp_name
);
1632 if (strlen(driver
->helpfile
)) {
1633 fstrcpy(temp_name
, driver
->helpfile
);
1634 slprintf(driver
->helpfile
, sizeof(driver
->helpfile
)-1, "%s%s", directory
, temp_name
);
1637 if (driver
->dependentfiles
) {
1638 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1639 fstrcpy(temp_name
, driver
->dependentfiles
[i
]);
1640 slprintf(driver
->dependentfiles
[i
], sizeof(driver
->dependentfiles
[i
])-1, "%s%s", directory
, temp_name
);
1644 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, driver
->cversion
, driver
->name
);
1646 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key
));
1653 len
+= tdb_pack(buf
+len
, buflen
-len
, "dffffffff",
1656 driver
->environment
,
1661 driver
->monitorname
,
1662 driver
->defaultdatatype
);
1664 if (driver
->dependentfiles
) {
1665 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1666 len
+= tdb_pack(buf
+len
, buflen
-len
, "f",
1667 driver
->dependentfiles
[i
]);
1671 if (len
!= buflen
) {
1674 tb
= (char *)Realloc(buf
, len
);
1676 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1687 kbuf
.dsize
= strlen(key
)+1;
1691 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
1695 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key
));
1701 /****************************************************************************
1702 ****************************************************************************/
1703 static uint32
add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
)
1705 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3
;
1708 info3
.cversion
= driver
->version
;
1709 fstrcpy(info3
.name
,driver
->name
);
1710 fstrcpy(info3
.environment
,driver
->environment
);
1711 fstrcpy(info3
.driverpath
,driver
->driverpath
);
1712 fstrcpy(info3
.datafile
,driver
->datafile
);
1713 fstrcpy(info3
.configfile
,driver
->configfile
);
1714 fstrcpy(info3
.helpfile
,driver
->helpfile
);
1715 fstrcpy(info3
.monitorname
,driver
->monitorname
);
1716 fstrcpy(info3
.defaultdatatype
,driver
->defaultdatatype
);
1717 info3
.dependentfiles
= driver
->dependentfiles
;
1719 return add_a_printer_driver_3(&info3
);
1723 /****************************************************************************
1724 ****************************************************************************/
1725 static WERROR
get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, const char *driver
, const char *arch
)
1727 NT_PRINTER_DRIVER_INFO_LEVEL_3 info
;
1731 fstrcpy(info
.name
, driver
);
1732 fstrcpy(info
.defaultdatatype
, "RAW");
1734 fstrcpy(info
.driverpath
, "");
1735 fstrcpy(info
.datafile
, "");
1736 fstrcpy(info
.configfile
, "");
1737 fstrcpy(info
.helpfile
, "");
1739 if ((info
.dependentfiles
=(fstring
*)malloc(2*sizeof(fstring
))) == NULL
)
1742 memset(info
.dependentfiles
, '\0', 2*sizeof(fstring
));
1743 fstrcpy(info
.dependentfiles
[0], "");
1745 *info_ptr
= memdup(&info
, sizeof(info
));
1750 /****************************************************************************
1751 ****************************************************************************/
1752 static WERROR
get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, fstring drivername
, const char *arch
, uint32 version
)
1754 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver
;
1755 TDB_DATA kbuf
, dbuf
;
1756 const char *architecture
;
1761 ZERO_STRUCT(driver
);
1763 architecture
= get_short_archi(arch
);
1765 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1767 if ( strcmp( architecture
, SPL_ARCH_WIN40
) == 0 )
1770 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX
, architecture
, version
, drivername
));
1772 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, version
, drivername
);
1775 kbuf
.dsize
= strlen(key
)+1;
1777 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
1779 return WERR_UNKNOWN_PRINTER_DRIVER
;
1781 len
+= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dffffffff",
1790 driver
.defaultdatatype
);
1793 while (len
< dbuf
.dsize
) {
1796 tddfs
= (fstring
*)Realloc(driver
.dependentfiles
,
1797 sizeof(fstring
)*(i
+2));
1798 if (tddfs
== NULL
) {
1799 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1802 else driver
.dependentfiles
= tddfs
;
1804 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "f",
1805 &driver
.dependentfiles
[i
]);
1809 if (driver
.dependentfiles
!= NULL
)
1810 fstrcpy(driver
.dependentfiles
[i
], "");
1812 SAFE_FREE(dbuf
.dptr
);
1814 if (len
!= dbuf
.dsize
) {
1815 SAFE_FREE(driver
.dependentfiles
);
1817 return get_a_printer_driver_3_default(info_ptr
, drivername
, arch
);
1820 *info_ptr
= (NT_PRINTER_DRIVER_INFO_LEVEL_3
*)memdup(&driver
, sizeof(driver
));
1825 /****************************************************************************
1826 Debugging function, dump at level 6 the struct in the logs.
1827 ****************************************************************************/
1829 static uint32
dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
1832 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
1835 DEBUG(20,("Dumping printer driver at level [%d]\n", level
));
1841 if (driver
.info_3
== NULL
)
1844 info3
=driver
.info_3
;
1846 DEBUGADD(20,("version:[%d]\n", info3
->cversion
));
1847 DEBUGADD(20,("name:[%s]\n", info3
->name
));
1848 DEBUGADD(20,("environment:[%s]\n", info3
->environment
));
1849 DEBUGADD(20,("driverpath:[%s]\n", info3
->driverpath
));
1850 DEBUGADD(20,("datafile:[%s]\n", info3
->datafile
));
1851 DEBUGADD(20,("configfile:[%s]\n", info3
->configfile
));
1852 DEBUGADD(20,("helpfile:[%s]\n", info3
->helpfile
));
1853 DEBUGADD(20,("monitorname:[%s]\n", info3
->monitorname
));
1854 DEBUGADD(20,("defaultdatatype:[%s]\n", info3
->defaultdatatype
));
1856 for (i
=0; info3
->dependentfiles
&&
1857 *info3
->dependentfiles
[i
]; i
++) {
1858 DEBUGADD(20,("dependentfile:[%s]\n",
1859 info3
->dependentfiles
[i
]));
1866 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level
));
1874 /****************************************************************************
1875 ****************************************************************************/
1876 int pack_devicemode(NT_DEVICEMODE
*nt_devmode
, char *buf
, int buflen
)
1880 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", nt_devmode
);
1885 len
+= tdb_pack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1886 nt_devmode
->devicename
,
1887 nt_devmode
->formname
,
1889 nt_devmode
->specversion
,
1890 nt_devmode
->driverversion
,
1892 nt_devmode
->driverextra
,
1893 nt_devmode
->orientation
,
1894 nt_devmode
->papersize
,
1895 nt_devmode
->paperlength
,
1896 nt_devmode
->paperwidth
,
1899 nt_devmode
->defaultsource
,
1900 nt_devmode
->printquality
,
1903 nt_devmode
->yresolution
,
1904 nt_devmode
->ttoption
,
1905 nt_devmode
->collate
,
1906 nt_devmode
->logpixels
,
1909 nt_devmode
->bitsperpel
,
1910 nt_devmode
->pelswidth
,
1911 nt_devmode
->pelsheight
,
1912 nt_devmode
->displayflags
,
1913 nt_devmode
->displayfrequency
,
1914 nt_devmode
->icmmethod
,
1915 nt_devmode
->icmintent
,
1916 nt_devmode
->mediatype
,
1917 nt_devmode
->dithertype
,
1918 nt_devmode
->reserved1
,
1919 nt_devmode
->reserved2
,
1920 nt_devmode
->panningwidth
,
1921 nt_devmode
->panningheight
,
1922 nt_devmode
->private);
1925 if (nt_devmode
->private) {
1926 len
+= tdb_pack(buf
+len
, buflen
-len
, "B",
1927 nt_devmode
->driverextra
,
1928 nt_devmode
->private);
1931 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode
->formname
));
1936 /****************************************************************************
1937 Pack all values in all printer keys
1938 ***************************************************************************/
1940 static int pack_values(NT_PRINTER_DATA
*data
, char *buf
, int buflen
)
1944 REGISTRY_VALUE
*val
;
1945 REGVAL_CTR
*val_ctr
;
1952 /* loop over all keys */
1954 for ( i
=0; i
<data
->num_keys
; i
++ ) {
1955 val_ctr
= &data
->keys
[i
].values
;
1956 num_values
= regval_ctr_numvals( val_ctr
);
1958 /* loop over all values */
1960 for ( j
=0; j
<num_values
; j
++ ) {
1961 /* pathname should be stored as <key>\<value> */
1963 val
= regval_ctr_specific_value( val_ctr
, j
);
1964 pstrcpy( path
, data
->keys
[i
].name
);
1965 pstrcat( path
, "\\" );
1966 pstrcat( path
, regval_name(val
) );
1968 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
1973 regval_data_p(val
) );
1980 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", NULL
);
1986 /****************************************************************************
1987 Delete a printer - this just deletes the printer info file, any open
1988 handles are not affected.
1989 ****************************************************************************/
1991 uint32
del_a_printer(char *sharename
)
1996 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
1999 kbuf
.dsize
=strlen(key
)+1;
2001 tdb_delete(tdb_printers
, kbuf
);
2005 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
2006 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
**, const char* sharename
);
2007 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**);
2008 /****************************************************************************
2009 ****************************************************************************/
2010 static WERROR
update_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
)
2016 TDB_DATA kbuf
, dbuf
;
2019 * in addprinter: no servername and the printer is the name
2020 * in setprinter: servername is \\server
2021 * and printer is \\server\\printer
2023 * Samba manages only local printers.
2024 * we currently don't support things like path=\\other_server\printer
2027 if (info
->servername
[0]!='\0') {
2028 trim_string(info
->printername
, info
->servername
, NULL
);
2029 trim_char(info
->printername
, '\\', '\0');
2030 info
->servername
[0]='\0';
2034 * JFM: one day I'll forget.
2035 * below that's info->portname because that's the SAMBA sharename
2036 * and I made NT 'thinks' it's the portname
2037 * the info->sharename is the thing you can name when you add a printer
2038 * that's the short-name when you create shared printer for 95/98
2039 * So I've made a limitation in SAMBA: you can only have 1 printer model
2040 * behind a SAMBA share.
2048 len
+= tdb_pack(buf
+len
, buflen
-len
, "dddddddddddfffffPfffff",
2051 info
->default_priority
,
2068 info
->printprocessor
,
2072 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
2074 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
2076 if (buflen
!= len
) {
2079 tb
= (char *)Realloc(buf
, len
);
2081 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2091 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, info
->sharename
);
2094 kbuf
.dsize
= strlen(key
)+1;
2098 ret
= (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) == 0? WERR_OK
: WERR_NOMEM
);
2101 if (!W_ERROR_IS_OK(ret
))
2102 DEBUG(8, ("error updating printer to tdb on disk\n"));
2106 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2107 info
->sharename
, info
->drivername
, info
->portname
, len
));
2113 /****************************************************************************
2114 Malloc and return an NT devicemode.
2115 ****************************************************************************/
2117 NT_DEVICEMODE
*construct_nt_devicemode(const fstring default_devicename
)
2120 char adevice
[MAXDEVICENAME
];
2121 NT_DEVICEMODE
*nt_devmode
= (NT_DEVICEMODE
*)malloc(sizeof(NT_DEVICEMODE
));
2123 if (nt_devmode
== NULL
) {
2124 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2128 ZERO_STRUCTP(nt_devmode
);
2130 safe_strcpy(adevice
, default_devicename
, sizeof(adevice
)-1);
2131 fstrcpy(nt_devmode
->devicename
, adevice
);
2133 fstrcpy(nt_devmode
->formname
, "Letter");
2135 nt_devmode
->specversion
= 0x0401;
2136 nt_devmode
->driverversion
= 0x0400;
2137 nt_devmode
->size
= 0x00DC;
2138 nt_devmode
->driverextra
= 0x0000;
2139 nt_devmode
->fields
= FORMNAME
| TTOPTION
| PRINTQUALITY
|
2140 DEFAULTSOURCE
| COPIES
| SCALE
|
2141 PAPERSIZE
| ORIENTATION
;
2142 nt_devmode
->orientation
= 1;
2143 nt_devmode
->papersize
= PAPER_LETTER
;
2144 nt_devmode
->paperlength
= 0;
2145 nt_devmode
->paperwidth
= 0;
2146 nt_devmode
->scale
= 0x64;
2147 nt_devmode
->copies
= 1;
2148 nt_devmode
->defaultsource
= BIN_FORMSOURCE
;
2149 nt_devmode
->printquality
= RES_HIGH
; /* 0x0258 */
2150 nt_devmode
->color
= COLOR_MONOCHROME
;
2151 nt_devmode
->duplex
= DUP_SIMPLEX
;
2152 nt_devmode
->yresolution
= 0;
2153 nt_devmode
->ttoption
= TT_SUBDEV
;
2154 nt_devmode
->collate
= COLLATE_FALSE
;
2155 nt_devmode
->icmmethod
= 0;
2156 nt_devmode
->icmintent
= 0;
2157 nt_devmode
->mediatype
= 0;
2158 nt_devmode
->dithertype
= 0;
2160 /* non utilisés par un driver d'imprimante */
2161 nt_devmode
->logpixels
= 0;
2162 nt_devmode
->bitsperpel
= 0;
2163 nt_devmode
->pelswidth
= 0;
2164 nt_devmode
->pelsheight
= 0;
2165 nt_devmode
->displayflags
= 0;
2166 nt_devmode
->displayfrequency
= 0;
2167 nt_devmode
->reserved1
= 0;
2168 nt_devmode
->reserved2
= 0;
2169 nt_devmode
->panningwidth
= 0;
2170 nt_devmode
->panningheight
= 0;
2172 nt_devmode
->private = NULL
;
2176 /****************************************************************************
2177 Deepcopy an NT devicemode.
2178 ****************************************************************************/
2180 NT_DEVICEMODE
*dup_nt_devicemode(NT_DEVICEMODE
*nt_devicemode
)
2182 NT_DEVICEMODE
*new_nt_devicemode
= NULL
;
2184 if ( !nt_devicemode
)
2187 if ((new_nt_devicemode
= (NT_DEVICEMODE
*)memdup(nt_devicemode
, sizeof(NT_DEVICEMODE
))) == NULL
) {
2188 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2192 new_nt_devicemode
->private = NULL
;
2193 if (nt_devicemode
->private != NULL
) {
2194 if ((new_nt_devicemode
->private = memdup(nt_devicemode
->private, nt_devicemode
->driverextra
)) == NULL
) {
2195 SAFE_FREE(new_nt_devicemode
);
2196 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2201 return new_nt_devicemode
;
2204 /****************************************************************************
2205 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2206 ****************************************************************************/
2208 void free_nt_devicemode(NT_DEVICEMODE
**devmode_ptr
)
2210 NT_DEVICEMODE
*nt_devmode
= *devmode_ptr
;
2212 if(nt_devmode
== NULL
)
2215 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2217 SAFE_FREE(nt_devmode
->private);
2218 SAFE_FREE(*devmode_ptr
);
2221 /****************************************************************************
2222 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2223 ****************************************************************************/
2224 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
)
2226 NT_PRINTER_INFO_LEVEL_2
*info
= *info_ptr
;
2227 NT_PRINTER_DATA
*data
;
2233 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2235 free_nt_devicemode(&info
->devmode
);
2237 /* clean up all registry keys */
2240 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2241 SAFE_FREE( data
->keys
[i
].name
);
2242 regval_ctr_destroy( &data
->keys
[i
].values
);
2244 SAFE_FREE( data
->keys
);
2246 /* finally the top level structure */
2248 SAFE_FREE( *info_ptr
);
2252 /****************************************************************************
2253 ****************************************************************************/
2254 int unpack_devicemode(NT_DEVICEMODE
**nt_devmode
, char *buf
, int buflen
)
2258 NT_DEVICEMODE devmode
;
2260 ZERO_STRUCT(devmode
);
2262 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2264 if (!*nt_devmode
) return len
;
2266 len
+= tdb_unpack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2270 &devmode
.specversion
,
2271 &devmode
.driverversion
,
2273 &devmode
.driverextra
,
2274 &devmode
.orientation
,
2276 &devmode
.paperlength
,
2277 &devmode
.paperwidth
,
2280 &devmode
.defaultsource
,
2281 &devmode
.printquality
,
2284 &devmode
.yresolution
,
2290 &devmode
.bitsperpel
,
2292 &devmode
.pelsheight
,
2293 &devmode
.displayflags
,
2294 &devmode
.displayfrequency
,
2298 &devmode
.dithertype
,
2301 &devmode
.panningwidth
,
2302 &devmode
.panningheight
,
2305 if (devmode
.private) {
2306 /* the len in tdb_unpack is an int value and
2307 * devmode.driverextra is only a short
2309 len
+= tdb_unpack(buf
+len
, buflen
-len
, "B", &extra_len
, &devmode
.private);
2310 devmode
.driverextra
=(uint16
)extra_len
;
2312 /* check to catch an invalid TDB entry so we don't segfault */
2313 if (devmode
.driverextra
== 0) {
2314 devmode
.private = NULL
;
2318 *nt_devmode
= (NT_DEVICEMODE
*)memdup(&devmode
, sizeof(devmode
));
2320 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode
.devicename
, devmode
.formname
));
2321 if (devmode
.private)
2322 DEBUG(8,("with a private section of %d bytes\n", devmode
.driverextra
));
2327 /****************************************************************************
2328 Allocate and initialize a new slot.
2329 ***************************************************************************/
2331 static int add_new_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2336 if ( !data
|| !name
)
2339 /* allocate another slot in the NT_PRINTER_KEY array */
2341 d
= Realloc( data
->keys
, sizeof(NT_PRINTER_KEY
)*(data
->num_keys
+1) );
2345 key_index
= data
->num_keys
;
2347 /* initialze new key */
2350 data
->keys
[key_index
].name
= strdup( name
);
2352 ZERO_STRUCTP( &data
->keys
[key_index
].values
);
2354 regval_ctr_init( &data
->keys
[key_index
].values
);
2356 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name
));
2361 /****************************************************************************
2362 search for a registry key name in the existing printer data
2363 ***************************************************************************/
2365 int lookup_printerkey( NT_PRINTER_DATA
*data
, const char *name
)
2370 if ( !data
|| !name
)
2373 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name
));
2375 /* loop over all existing keys */
2377 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2378 if ( strequal(data
->keys
[i
].name
, name
) ) {
2379 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name
));
2389 /****************************************************************************
2390 ***************************************************************************/
2392 uint32
get_printer_subkeys( NT_PRINTER_DATA
*data
, const char* key
, fstring
**subkeys
)
2396 int num_subkeys
= 0;
2398 fstring
*ptr
, *subkeys_ptr
= NULL
;
2404 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2405 if ( StrnCaseCmp(data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2406 /* match sure it is a subkey and not the key itself */
2408 key_len
= strlen( key
);
2409 if ( strlen(data
->keys
[i
].name
) == key_len
)
2412 /* get subkey path */
2414 p
= data
->keys
[i
].name
+ key_len
;
2417 fstrcpy( subkeyname
, p
);
2418 if ( (p
= strchr( subkeyname
, '\\' )) )
2421 /* don't add a key more than once */
2423 for ( j
=0; j
<num_subkeys
; j
++ ) {
2424 if ( strequal( subkeys_ptr
[j
], subkeyname
) )
2428 if ( j
!= num_subkeys
)
2431 /* found a match, so allocate space and copy the name */
2433 if ( !(ptr
= Realloc( subkeys_ptr
, (num_subkeys
+2)*sizeof(fstring
))) ) {
2434 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2436 SAFE_FREE( subkeys
);
2441 fstrcpy( subkeys_ptr
[num_subkeys
], subkeyname
);
2447 /* tag of the end */
2450 fstrcpy(subkeys_ptr
[num_subkeys
], "" );
2452 *subkeys
= subkeys_ptr
;
2458 static void map_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2461 smb_ucs2_t conv_str
[1024];
2464 regval_ctr_delvalue(ctr
, val_name
);
2465 str_size
= push_ucs2(NULL
, conv_str
, sz
, sizeof(conv_str
),
2466 STR_TERMINATE
| STR_NOALIGN
);
2467 regval_ctr_addvalue(ctr
, val_name
, REG_SZ
,
2468 (char *) conv_str
, str_size
);
2471 static void map_dword_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2474 regval_ctr_delvalue(ctr
, val_name
);
2475 regval_ctr_addvalue(ctr
, val_name
, REG_DWORD
,
2476 (char *) &dword
, sizeof(dword
));
2479 static void map_bool_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2482 uint8 bin_bool
= (b
? 1 : 0);
2483 regval_ctr_delvalue(ctr
, val_name
);
2484 regval_ctr_addvalue(ctr
, val_name
, REG_BINARY
,
2485 (char *) &bin_bool
, sizeof(bin_bool
));
2488 static void map_single_multi_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2489 const char *multi_sz
)
2491 smb_ucs2_t
*conv_strs
= NULL
;
2494 /* a multi-sz has to have a null string terminator, i.e., the last
2495 string must be followed by two nulls */
2496 str_size
= (strlen(multi_sz
) + 2) * sizeof(smb_ucs2_t
);
2497 conv_strs
= calloc(str_size
, 1);
2499 push_ucs2(NULL
, conv_strs
, multi_sz
, str_size
,
2500 STR_TERMINATE
| STR_NOALIGN
);
2502 regval_ctr_delvalue(ctr
, val_name
);
2503 regval_ctr_addvalue(ctr
, val_name
, REG_MULTI_SZ
,
2504 (char *) conv_strs
, str_size
);
2505 safe_free(conv_strs
);
2509 /****************************************************************************
2510 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2512 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2513 * @return BOOL indicating success or failure
2514 ***************************************************************************/
2516 static BOOL
map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2
*info2
)
2518 REGVAL_CTR
*ctr
= NULL
;
2520 char *allocated_string
= NULL
;
2521 const char *ascii_str
;
2524 if ((i
= lookup_printerkey(&info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2525 i
= add_new_printer_key(&info2
->data
, SPOOL_DSSPOOLER_KEY
);
2526 ctr
= &info2
->data
.keys
[i
].values
;
2528 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTERNAME
, info2
->sharename
);
2529 map_sz_into_ctr(ctr
, SPOOL_REG_SHORTSERVERNAME
, global_myname());
2531 get_myfullname(longname
);
2532 map_sz_into_ctr(ctr
, SPOOL_REG_SERVERNAME
, longname
);
2534 asprintf(&allocated_string
, "\\\\%s\\%s", longname
, info2
->sharename
);
2535 map_sz_into_ctr(ctr
, SPOOL_REG_UNCNAME
, allocated_string
);
2536 SAFE_FREE(allocated_string
);
2538 map_dword_into_ctr(ctr
, SPOOL_REG_VERSIONNUMBER
, 4);
2539 map_sz_into_ctr(ctr
, SPOOL_REG_DRIVERNAME
, info2
->drivername
);
2540 map_sz_into_ctr(ctr
, SPOOL_REG_LOCATION
, info2
->location
);
2541 map_sz_into_ctr(ctr
, SPOOL_REG_DESCRIPTION
, info2
->comment
);
2542 map_single_multi_sz_into_ctr(ctr
, SPOOL_REG_PORTNAME
, info2
->portname
);
2543 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSEPARATORFILE
, info2
->sepfile
);
2544 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTSTARTTIME
, info2
->starttime
);
2545 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTENDTIME
, info2
->untiltime
);
2546 map_dword_into_ctr(ctr
, SPOOL_REG_PRIORITY
, info2
->priority
);
2548 map_bool_into_ctr(ctr
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
2549 (info2
->attributes
&
2550 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
2552 switch (info2
->attributes
& 0x3) {
2554 ascii_str
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
2557 ascii_str
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
2560 ascii_str
= SPOOL_REGVAL_PRINTDIRECT
;
2563 ascii_str
= "unknown";
2565 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSPOOLING
, ascii_str
);
2570 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2
*info2
, GUID guid
)
2573 REGVAL_CTR
*ctr
=NULL
;
2575 /* find the DsSpooler key */
2576 if ((i
= lookup_printerkey(&info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2577 i
= add_new_printer_key(&info2
->data
, SPOOL_DSSPOOLER_KEY
);
2578 ctr
= &info2
->data
.keys
[i
].values
;
2580 regval_ctr_delvalue(ctr
, "objectGUID");
2581 regval_ctr_addvalue(ctr
, "objectGUID", REG_BINARY
,
2582 (char *) &guid
, sizeof(GUID
));
2585 static WERROR
publish_it(NT_PRINTER_INFO_LEVEL
*printer
)
2588 TALLOC_CTX
*ctx
= talloc_init("publish_it");
2589 ADS_MODLIST mods
= ads_init_mods(ctx
);
2590 char *prt_dn
= NULL
, *srv_dn
, **srv_cn
;
2593 const char *attrs
[] = {"objectGUID", NULL
};
2595 WERROR win_rc
= WERR_OK
;
2598 /* set the DsSpooler info and attributes */
2599 if (!(map_nt_printer_info2_to_dsspooler(printer
->info_2
)))
2601 printer
->info_2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
2602 win_rc
= mod_a_printer(*printer
, 2);
2603 if (!W_ERROR_IS_OK(win_rc
)) {
2604 DEBUG(3, ("err %d saving data\n",
2605 W_ERROR_V(win_rc
)));
2609 /* Build the ads mods */
2610 get_local_printer_publishing_data(ctx
, &mods
,
2611 &printer
->info_2
->data
);
2612 ads_mod_str(ctx
, &mods
, SPOOL_REG_PRINTERNAME
,
2613 printer
->info_2
->sharename
);
2615 /* initial ads structure */
2617 ads
= ads_init(NULL
, NULL
, NULL
);
2619 DEBUG(3, ("ads_init() failed\n"));
2620 return WERR_SERVER_UNAVAILABLE
;
2622 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
2623 SAFE_FREE(ads
->auth
.password
);
2624 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
2627 /* ads_connect() will find the DC for us */
2628 ads_rc
= ads_connect(ads
);
2629 if (!ADS_ERR_OK(ads_rc
)) {
2630 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
2632 return WERR_ACCESS_DENIED
;
2635 /* figure out where to publish */
2636 ads_find_machine_acct(ads
, &res
, global_myname());
2637 srv_dn
= ldap_get_dn(ads
->ld
, res
);
2638 ads_msgfree(ads
, res
);
2639 srv_cn
= ldap_explode_dn(srv_dn
, 1);
2640 asprintf(&prt_dn
, "cn=%s-%s,%s", srv_cn
[0],
2641 printer
->info_2
->sharename
, srv_dn
);
2642 ads_memfree(ads
, srv_dn
);
2645 ads_rc
= ads_add_printer_entry(ads
, prt_dn
, ctx
, &mods
);
2646 if (LDAP_ALREADY_EXISTS
== ads_rc
.err
.rc
)
2647 ads_rc
= ads_mod_printer_entry(ads
, prt_dn
, ctx
,&mods
);
2649 /* retreive the guid and store it locally */
2650 if (ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
2651 ads_memfree(ads
, prt_dn
);
2652 ads_pull_guid(ads
, res
, &guid
);
2653 ads_msgfree(ads
, res
);
2654 store_printer_guid(printer
->info_2
, guid
);
2655 win_rc
= mod_a_printer(*printer
, 2);
2664 WERROR
unpublish_it(NT_PRINTER_INFO_LEVEL
*printer
)
2669 char *prt_dn
= NULL
;
2672 printer
->info_2
->attributes
^= PRINTER_ATTRIBUTE_PUBLISHED
;
2673 win_rc
= mod_a_printer(*printer
, 2);
2674 if (!W_ERROR_IS_OK(win_rc
)) {
2675 DEBUG(3, ("err %d saving data\n",
2676 W_ERROR_V(win_rc
)));
2680 ads
= ads_init(NULL
, NULL
, NULL
);
2682 DEBUG(3, ("ads_init() failed\n"));
2683 return WERR_SERVER_UNAVAILABLE
;
2685 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
2686 SAFE_FREE(ads
->auth
.password
);
2687 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
2690 /* ads_connect() will find the DC for us */
2691 ads_rc
= ads_connect(ads
);
2692 if (!ADS_ERR_OK(ads_rc
)) {
2693 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
2695 return WERR_ACCESS_DENIED
;
2698 /* remove the printer from the directory */
2699 ads_rc
= ads_find_printer_on_server(ads
, &res
,
2700 printer
->info_2
->sharename
, global_myname());
2701 if (ADS_ERR_OK(ads_rc
) && ads_count_replies(ads
, res
)) {
2702 prt_dn
= ads_get_dn(ads
, res
);
2703 ads_msgfree(ads
, res
);
2704 ads_rc
= ads_del_dn(ads
, prt_dn
);
2705 ads_memfree(ads
, prt_dn
);
2712 /****************************************************************************
2713 * Publish a printer in the directory
2715 * @param snum describing printer service
2716 * @return WERROR indicating status of publishing
2717 ***************************************************************************/
2719 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
2721 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2724 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
2725 if (!W_ERROR_IS_OK(win_rc
))
2729 case SPOOL_DS_PUBLISH
:
2730 case SPOOL_DS_UPDATE
:
2731 win_rc
= publish_it(printer
);
2733 case SPOOL_DS_UNPUBLISH
:
2734 win_rc
= unpublish_it(printer
);
2737 win_rc
= WERR_NOT_SUPPORTED
;
2741 free_a_printer(&printer
, 2);
2745 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
, GUID
*guid
)
2747 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2749 REGISTRY_VALUE
*guid_val
;
2754 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
2755 if (!W_ERROR_IS_OK(win_rc
))
2758 if (!(printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
))
2761 if ((i
= lookup_printerkey(&printer
->info_2
->data
,
2762 SPOOL_DSSPOOLER_KEY
)) < 0)
2765 if (!(ctr
= &printer
->info_2
->data
.keys
[i
].values
)) {
2769 if (!(guid_val
= regval_ctr_getvalue(ctr
, "objectGUID"))) {
2773 if (regval_size(guid_val
) == sizeof(GUID
))
2774 memcpy(guid
, regval_data_p(guid_val
), sizeof(GUID
));
2780 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
2784 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
, GUID
*guid
)
2789 /****************************************************************************
2790 ***************************************************************************/
2792 WERROR
delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
)
2794 NT_PRINTER_DATA
*data
;
2796 int removed_keys
= 0;
2800 empty_slot
= data
->num_keys
;
2803 return WERR_INVALID_PARAM
;
2805 /* remove all keys */
2807 if ( !strlen(key
) ) {
2808 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2809 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2810 data
->keys
[i
].name
));
2812 SAFE_FREE( data
->keys
[i
].name
);
2813 regval_ctr_destroy( &data
->keys
[i
].values
);
2816 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2819 SAFE_FREE( data
->keys
);
2820 ZERO_STRUCTP( data
);
2825 /* remove a specific key (and all subkeys) */
2827 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2828 if ( StrnCaseCmp( data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2829 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2830 data
->keys
[i
].name
));
2832 SAFE_FREE( data
->keys
[i
].name
);
2833 regval_ctr_destroy( &data
->keys
[i
].values
);
2835 /* mark the slot as empty */
2837 ZERO_STRUCTP( &data
->keys
[i
] );
2841 /* find the first empty slot */
2843 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2844 if ( !data
->keys
[i
].name
) {
2851 if ( i
== data
->num_keys
)
2852 /* nothing was removed */
2853 return WERR_INVALID_PARAM
;
2855 /* move everything down */
2857 for ( i
=empty_slot
+1; i
<data
->num_keys
; i
++ ) {
2858 if ( data
->keys
[i
].name
) {
2859 memcpy( &data
->keys
[empty_slot
], &data
->keys
[i
], sizeof(NT_PRINTER_KEY
) );
2860 ZERO_STRUCTP( &data
->keys
[i
] );
2868 data
->num_keys
-= removed_keys
;
2870 /* sanity check to see if anything is left */
2872 if ( !data
->num_keys
) {
2873 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2
->printername
));
2875 SAFE_FREE( data
->keys
);
2876 ZERO_STRUCTP( data
);
2882 /****************************************************************************
2883 ***************************************************************************/
2885 WERROR
delete_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
2887 WERROR result
= WERR_OK
;
2890 /* we must have names on non-zero length */
2892 if ( !key
|| !*key
|| !value
|| !*value
)
2893 return WERR_INVALID_NAME
;
2895 /* find the printer key first */
2897 key_index
= lookup_printerkey( &p2
->data
, key
);
2898 if ( key_index
== -1 )
2901 /* make sure the value exists so we can return the correct error code */
2903 if ( !regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
) )
2904 return WERR_BADFILE
;
2906 regval_ctr_delvalue( &p2
->data
.keys
[key_index
].values
, value
);
2908 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2914 /****************************************************************************
2915 ***************************************************************************/
2917 WERROR
add_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
,
2918 uint32 type
, uint8
*data
, int real_len
)
2920 WERROR result
= WERR_OK
;
2923 /* we must have names on non-zero length */
2925 if ( !key
|| !*key
|| !value
|| !*value
)
2926 return WERR_INVALID_NAME
;
2928 /* find the printer key first */
2930 key_index
= lookup_printerkey( &p2
->data
, key
);
2931 if ( key_index
== -1 )
2932 key_index
= add_new_printer_key( &p2
->data
, key
);
2934 if ( key_index
== -1 )
2937 regval_ctr_addvalue( &p2
->data
.keys
[key_index
].values
, value
,
2938 type
, (const char *)data
, real_len
);
2940 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
2941 key
, value
, type
, real_len
));
2946 /****************************************************************************
2947 ***************************************************************************/
2949 REGISTRY_VALUE
* get_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
2953 if ( (key_index
= lookup_printerkey( &p2
->data
, key
)) == -1 )
2956 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
2959 return regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
);
2962 /****************************************************************************
2963 Unpack a list of registry values frem the TDB
2964 ***************************************************************************/
2966 static int unpack_values(NT_PRINTER_DATA
*printer_data
, char *buf
, int buflen
)
2970 pstring string
, valuename
, keyname
;
2974 REGISTRY_VALUE
*regval_p
;
2977 /* add the "PrinterDriverData" key first for performance reasons */
2979 add_new_printer_key( printer_data
, SPOOL_PRINTERDATA_KEY
);
2981 /* loop and unpack the rest of the registry values */
2985 /* check to see if there are any more registry values */
2987 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", ®val_p
);
2991 /* unpack the next regval */
2993 len
+= tdb_unpack(buf
+len
, buflen
-len
, "fdB",
3000 * break of the keyname from the value name.
3001 * Should only be one '\' in the string returned.
3004 str
= strrchr( string
, '\\');
3006 /* Put in "PrinterDriverData" is no key specified */
3009 pstrcpy( keyname
, SPOOL_PRINTERDATA_KEY
);
3010 pstrcpy( valuename
, string
);
3014 pstrcpy( keyname
, string
);
3015 pstrcpy( valuename
, str
+1 );
3018 /* see if we need a new key */
3020 if ( (key_index
=lookup_printerkey( printer_data
, keyname
)) == -1 )
3021 key_index
= add_new_printer_key( printer_data
, keyname
);
3023 if ( key_index
== -1 ) {
3024 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3029 /* add the new value */
3031 regval_ctr_addvalue( &printer_data
->keys
[key_index
].values
, valuename
, type
, (const char *)data_p
, size
);
3033 SAFE_FREE(data_p
); /* 'B' option to tdbpack does a malloc() */
3035 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname
, valuename
, size
));
3041 /****************************************************************************
3042 ***************************************************************************/
3044 static void map_to_os2_driver(fstring drivername
)
3046 static BOOL initialised
=False
;
3047 static fstring last_from
,last_to
;
3048 char *mapfile
= lp_os2_driver_map();
3049 char **lines
= NULL
;
3053 if (!strlen(drivername
))
3060 *last_from
= *last_to
= 0;
3064 if (strequal(drivername
,last_from
)) {
3065 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,last_to
));
3066 fstrcpy(drivername
,last_to
);
3070 lines
= file_lines_load(mapfile
, &numlines
);
3071 if (numlines
== 0) {
3072 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile
));
3076 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
3078 for( i
= 0; i
< numlines
; i
++) {
3079 char *nt_name
= lines
[i
];
3080 char *os2_name
= strchr(nt_name
,'=');
3087 while (isspace(*nt_name
))
3090 if (!*nt_name
|| strchr("#;",*nt_name
))
3094 int l
= strlen(nt_name
);
3095 while (l
&& isspace(nt_name
[l
-1])) {
3101 while (isspace(*os2_name
))
3105 int l
= strlen(os2_name
);
3106 while (l
&& isspace(os2_name
[l
-1])) {
3112 if (strequal(nt_name
,drivername
)) {
3113 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername
,os2_name
));
3114 fstrcpy(last_from
,drivername
);
3115 fstrcpy(last_to
,os2_name
);
3116 fstrcpy(drivername
,os2_name
);
3117 file_lines_free(lines
);
3122 file_lines_free(lines
);
3125 /****************************************************************************
3126 Get a default printer info 2 struct.
3127 ****************************************************************************/
3128 static WERROR
get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, const char *sharename
)
3131 NT_PRINTER_INFO_LEVEL_2 info
;
3135 snum
= lp_servicenumber(sharename
);
3137 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", get_called_name());
3138 slprintf(info
.printername
, sizeof(info
.printername
)-1, "\\\\%s\\%s",
3139 get_called_name(), sharename
);
3140 fstrcpy(info
.sharename
, sharename
);
3141 fstrcpy(info
.portname
, SAMBA_PRINTER_PORT_NAME
);
3143 /* by setting the driver name to an empty string, a local NT admin
3144 can now run the **local** APW to install a local printer driver
3145 for a Samba shared printer in 2.2. Without this, drivers **must** be
3146 installed on the Samba server for NT clients --jerry */
3147 #if 0 /* JERRY --do not uncomment-- */
3148 if (!*info
.drivername
)
3149 fstrcpy(info
.drivername
, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3153 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info
.drivername
));
3155 pstrcpy(info
.comment
, "");
3156 fstrcpy(info
.printprocessor
, "winprint");
3157 fstrcpy(info
.datatype
, "RAW");
3159 info
.attributes
= PRINTER_ATTRIBUTE_SAMBA
;
3161 info
.starttime
= 0; /* Minutes since 12:00am GMT */
3162 info
.untiltime
= 0; /* Minutes since 12:00am GMT */
3164 info
.default_priority
= 1;
3165 info
.setuptime
= (uint32
)time(NULL
);
3168 * I changed this as I think it is better to have a generic
3169 * DEVMODE than to crash Win2k explorer.exe --jerry
3170 * See the HP Deskjet 990c Win2k drivers for an example.
3172 * However the default devmode appears to cause problems
3173 * with the HP CLJ 8500 PCL driver. Hence the addition of
3174 * the "default devmode" parameter --jerry 22/01/2002
3177 if (lp_default_devmode(snum
)) {
3178 if ((info
.devmode
= construct_nt_devicemode(info
.printername
)) == NULL
)
3182 info
.devmode
= NULL
;
3185 /* This will get the current RPC talloc context, but we should be
3186 passing this as a parameter... fixme... JRA ! */
3188 if (!nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
))
3191 *info_ptr
= (NT_PRINTER_INFO_LEVEL_2
*)memdup(&info
, sizeof(info
));
3193 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3201 free_nt_devicemode(&info
.devmode
);
3202 return WERR_ACCESS_DENIED
;
3205 /****************************************************************************
3206 ****************************************************************************/
3207 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, const char *sharename
)
3210 NT_PRINTER_INFO_LEVEL_2 info
;
3212 TDB_DATA kbuf
, dbuf
;
3213 fstring printername
;
3214 char adevice
[MAXDEVICENAME
];
3218 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
3221 kbuf
.dsize
= strlen(key
)+1;
3223 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
3225 return get_a_printer_2_default(info_ptr
, sharename
);
3227 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "dddddddddddfffffPfffff",
3230 &info
.default_priority
,
3247 info
.printprocessor
,
3251 /* Samba has to have shared raw drivers. */
3252 info
.attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
3254 /* Restore the stripped strings. */
3255 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", get_called_name());
3256 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", get_called_name(),
3258 fstrcpy(info
.printername
, printername
);
3260 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3263 * Some client drivers freak out if there is a NULL devmode
3264 * (probably the driver is not checking before accessing
3265 * the devmode pointer) --jerry
3267 * See comments in get_a_printer_2_default()
3270 if (lp_default_devmode(lp_servicenumber(sharename
)) && !info
.devmode
) {
3271 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3273 info
.devmode
= construct_nt_devicemode(printername
);
3276 safe_strcpy(adevice
, info
.printername
, sizeof(adevice
)-1);
3277 fstrcpy(info
.devmode
->devicename
, adevice
);
3280 len
+= unpack_values( &info
.data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3282 /* This will get the current RPC talloc context, but we should be
3283 passing this as a parameter... fixme... JRA ! */
3285 nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
);
3287 /* Fix for OS/2 drivers. */
3289 if (get_remote_arch() == RA_OS2
)
3290 map_to_os2_driver(info
.drivername
);
3292 SAFE_FREE(dbuf
.dptr
);
3293 *info_ptr
=memdup(&info
, sizeof(info
));
3295 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3296 sharename
, info
.printername
, info
.drivername
));
3301 /****************************************************************************
3302 Debugging function, dump at level 6 the struct in the logs.
3303 ****************************************************************************/
3304 static uint32
dump_a_printer(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3307 NT_PRINTER_INFO_LEVEL_2
*info2
;
3309 DEBUG(106,("Dumping printer at level [%d]\n", level
));
3314 if (printer
.info_2
== NULL
)
3318 info2
=printer
.info_2
;
3320 DEBUGADD(106,("attributes:[%d]\n", info2
->attributes
));
3321 DEBUGADD(106,("priority:[%d]\n", info2
->priority
));
3322 DEBUGADD(106,("default_priority:[%d]\n", info2
->default_priority
));
3323 DEBUGADD(106,("starttime:[%d]\n", info2
->starttime
));
3324 DEBUGADD(106,("untiltime:[%d]\n", info2
->untiltime
));
3325 DEBUGADD(106,("status:[%d]\n", info2
->status
));
3326 DEBUGADD(106,("cjobs:[%d]\n", info2
->cjobs
));
3327 DEBUGADD(106,("averageppm:[%d]\n", info2
->averageppm
));
3328 DEBUGADD(106,("changeid:[%d]\n", info2
->changeid
));
3329 DEBUGADD(106,("c_setprinter:[%d]\n", info2
->c_setprinter
));
3330 DEBUGADD(106,("setuptime:[%d]\n", info2
->setuptime
));
3332 DEBUGADD(106,("servername:[%s]\n", info2
->servername
));
3333 DEBUGADD(106,("printername:[%s]\n", info2
->printername
));
3334 DEBUGADD(106,("sharename:[%s]\n", info2
->sharename
));
3335 DEBUGADD(106,("portname:[%s]\n", info2
->portname
));
3336 DEBUGADD(106,("drivername:[%s]\n", info2
->drivername
));
3337 DEBUGADD(106,("comment:[%s]\n", info2
->comment
));
3338 DEBUGADD(106,("location:[%s]\n", info2
->location
));
3339 DEBUGADD(106,("sepfile:[%s]\n", info2
->sepfile
));
3340 DEBUGADD(106,("printprocessor:[%s]\n", info2
->printprocessor
));
3341 DEBUGADD(106,("datatype:[%s]\n", info2
->datatype
));
3342 DEBUGADD(106,("parameters:[%s]\n", info2
->parameters
));
3348 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level
));
3356 /****************************************************************************
3357 Update the changeid time.
3358 This is SO NASTY as some drivers need this to change, others need it
3359 static. This value will change every second, and I must hope that this
3360 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3362 ****************************************************************************/
3364 static uint32
rev_changeid(void)
3368 get_process_uptime(&tv
);
3371 /* Return changeid as msec since spooler restart */
3372 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
3375 * This setting seems to work well but is too untested
3376 * to replace the above calculation. Left in for experiementation
3377 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3379 return tv
.tv_sec
* 10 + tv
.tv_usec
/ 100000;
3384 * The function below are the high level ones.
3385 * only those ones must be called from the spoolss code.
3389 /****************************************************************************
3390 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3391 ****************************************************************************/
3393 WERROR
mod_a_printer(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3397 dump_a_printer(printer
, level
);
3400 * invalidate cache for all open handles to this printer.
3401 * cache for a given handle will be updated on the next
3405 invalidate_printer_hnd_cache( printer
.info_2
->sharename
);
3411 * Update the changestamp. Emperical tests show that the
3412 * ChangeID is always updated,but c_setprinter is
3413 * global spooler variable (not per printer).
3416 /* ChangeID **must** be increasing over the lifetime
3417 of client's spoolss service in order for the
3418 client's cache to show updates */
3420 printer
.info_2
->changeid
= rev_changeid();
3423 * Because one day someone will ask:
3424 * NT->NT An admin connection to a remote
3425 * printer show changes imeediately in
3426 * the properities dialog
3428 * A non-admin connection will only show the
3429 * changes after viewing the properites page
3430 * 2 times. Seems to be related to a
3431 * race condition in the client between the spooler
3432 * updating the local cache and the Explorer.exe GUI
3433 * actually displaying the properties.
3435 * This is fixed in Win2k. admin/non-admin
3436 * connections both display changes immediately.
3441 result
=update_a_printer_2(printer
.info_2
);
3446 result
=WERR_UNKNOWN_LEVEL
;
3453 /****************************************************************************
3454 Initialize printer devmode & data with previously saved driver init values.
3455 ****************************************************************************/
3457 static BOOL
set_driver_init_2( NT_PRINTER_INFO_LEVEL_2
*info_ptr
)
3461 TDB_DATA kbuf
, dbuf
;
3462 NT_PRINTER_INFO_LEVEL_2 info
;
3468 * Delete any printer data 'values' already set. When called for driver
3469 * replace, there will generally be some, but during an add printer, there
3470 * should not be any (if there are delete them).
3473 delete_all_printer_data( info_ptr
, "" );
3475 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info_ptr
->drivername
);
3478 kbuf
.dsize
= strlen(key
)+1;
3480 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
3483 * When changing to a driver that has no init info in the tdb, remove
3484 * the previous drivers init info and leave the new on blank.
3486 free_nt_devicemode(&info_ptr
->devmode
);
3491 * Get the saved DEVMODE..
3494 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3497 * The saved DEVMODE contains the devicename from the printer used during
3498 * the initialization save. Change it to reflect the new printer.
3501 if ( info
.devmode
) {
3502 ZERO_STRUCT(info
.devmode
->devicename
);
3503 fstrcpy(info
.devmode
->devicename
, info_ptr
->printername
);
3507 * NT/2k does not change out the entire DeviceMode of a printer
3508 * when changing the driver. Only the driverextra, private, &
3509 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3511 * Later examination revealed that Windows NT/2k does reset the
3512 * the printer's device mode, bit **only** when you change a
3513 * property of the device mode such as the page orientation.
3518 /* Bind the saved DEVMODE to the new the printer */
3520 free_nt_devicemode(&info_ptr
->devmode
);
3521 info_ptr
->devmode
= info
.devmode
;
3523 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3524 info_ptr
->printername
, info_ptr
->devmode
?"VALID":"NULL", info_ptr
->drivername
));
3526 /* Add the printer data 'values' to the new printer */
3528 len
+= unpack_values( &info_ptr
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3531 SAFE_FREE(dbuf
.dptr
);
3536 /****************************************************************************
3537 Initialize printer devmode & data with previously saved driver init values.
3538 When a printer is created using AddPrinter, the drivername bound to the
3539 printer is used to lookup previously saved driver initialization info, which
3540 is bound to the new printer.
3541 ****************************************************************************/
3543 BOOL
set_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3545 BOOL result
= False
;
3549 result
= set_driver_init_2(printer
->info_2
);
3553 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3561 /****************************************************************************
3562 Delete driver init data stored for a specified driver
3563 ****************************************************************************/
3565 BOOL
del_driver_init(char *drivername
)
3570 if (!drivername
|| !*drivername
) {
3571 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3575 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, drivername
);
3578 kbuf
.dsize
= strlen(key
)+1;
3580 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername
));
3582 return (tdb_delete(tdb_drivers
, kbuf
) == 0);
3585 /****************************************************************************
3586 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3587 in the tdb. Note: this is different from the driver entry and the printer
3588 entry. There should be a single driver init entry for each driver regardless
3589 of whether it was installed from NT or 2K. Technically, they should be
3590 different, but they work out to the same struct.
3591 ****************************************************************************/
3593 static uint32
update_driver_init_2(NT_PRINTER_INFO_LEVEL_2
*info
)
3597 int buflen
, len
, ret
;
3598 TDB_DATA kbuf
, dbuf
;
3605 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
3607 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
3609 if (buflen
!= len
) {
3612 tb
= (char *)Realloc(buf
, len
);
3614 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3624 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info
->drivername
);
3627 kbuf
.dsize
= strlen(key
)+1;
3631 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
3635 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3639 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3640 info
->sharename
, info
->drivername
));
3645 /****************************************************************************
3646 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3647 ****************************************************************************/
3649 uint32
update_driver_init(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3653 dump_a_printer(printer
, level
);
3657 result
= update_driver_init_2(printer
.info_2
);
3667 /****************************************************************************
3668 Convert the printer data value, a REG_BINARY array, into an initialization
3669 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3670 got to keep the endians happy :).
3671 ****************************************************************************/
3673 static BOOL
convert_driver_init( TALLOC_CTX
*ctx
, NT_DEVICEMODE
*nt_devmode
, uint8
*data
, uint32 data_len
)
3675 BOOL result
= False
;
3679 ZERO_STRUCT(devmode
);
3681 prs_init(&ps
, 0, ctx
, UNMARSHALL
);
3682 ps
.data_p
= (char *)data
;
3683 ps
.buffer_size
= data_len
;
3685 if (spoolss_io_devmode("phantom DEVMODE", &ps
, 0, &devmode
))
3686 result
= convert_devicemode("", &devmode
, &nt_devmode
);
3688 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3693 /****************************************************************************
3694 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3696 1. Use the driver's config DLL to this UNC printername and:
3697 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3698 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3699 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3701 The last step triggers saving the "driver initialization" information for
3702 this printer into the tdb. Later, new printers that use this driver will
3703 have this initialization information bound to them. This simulates the
3704 driver initialization, as if it had run on the Samba server (as it would
3707 The Win32 client side code requirement sucks! But until we can run arbitrary
3708 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3710 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3711 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3712 about it and you will realize why. JRR 010720
3713 ****************************************************************************/
3715 static WERROR
save_driver_init_2(NT_PRINTER_INFO_LEVEL
*printer
, uint8
*data
, uint32 data_len
)
3717 WERROR status
= WERR_OK
;
3718 TALLOC_CTX
*ctx
= NULL
;
3719 NT_DEVICEMODE
*nt_devmode
= NULL
;
3720 NT_DEVICEMODE
*tmp_devmode
= printer
->info_2
->devmode
;
3723 * When the DEVMODE is already set on the printer, don't try to unpack it.
3725 DEBUG(8,("save_driver_init_2: Enter...\n"));
3727 if ( !printer
->info_2
->devmode
&& data_len
) {
3729 * Set devmode on printer info, so entire printer initialization can be
3733 if ((ctx
= talloc_init("save_driver_init_2")) == NULL
)
3736 if ((nt_devmode
= (NT_DEVICEMODE
*)malloc(sizeof(NT_DEVICEMODE
))) == NULL
) {
3737 status
= WERR_NOMEM
;
3741 ZERO_STRUCTP(nt_devmode
);
3744 * The DEVMODE is held in the 'data' component of the param in raw binary.
3745 * Convert it to to a devmode structure
3747 if ( !convert_driver_init( ctx
, nt_devmode
, data
, data_len
)) {
3748 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3749 status
= WERR_INVALID_PARAM
;
3753 printer
->info_2
->devmode
= nt_devmode
;
3757 * Pack up and add (or update) the DEVMODE and any current printer data to
3758 * a 'driver init' element in the tdb
3762 if ( update_driver_init(*printer
, 2) != 0 ) {
3763 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3764 status
= WERR_NOMEM
;
3769 * If driver initialization info was successfully saved, set the current
3770 * printer to match it. This allows initialization of the current printer
3771 * as well as the driver.
3773 status
= mod_a_printer(*printer
, 2);
3774 if (!W_ERROR_IS_OK(status
)) {
3775 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3776 printer
->info_2
->printername
));
3780 talloc_destroy(ctx
);
3781 free_nt_devicemode( &nt_devmode
);
3783 printer
->info_2
->devmode
= tmp_devmode
;
3788 /****************************************************************************
3789 Update the driver init info (DEVMODE and specifics) for a printer
3790 ****************************************************************************/
3792 WERROR
save_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
, uint8
*data
, uint32 data_len
)
3794 WERROR status
= WERR_OK
;
3798 status
= save_driver_init_2( printer
, data
, data_len
);
3801 status
= WERR_UNKNOWN_LEVEL
;
3808 /****************************************************************************
3809 Deep copy a NT_PRINTER_DATA
3810 ****************************************************************************/
3812 static NTSTATUS
copy_printer_data( NT_PRINTER_DATA
*dst
, NT_PRINTER_DATA
*src
)
3814 int i
, j
, num_vals
, new_key_index
;
3815 REGVAL_CTR
*src_key
, *dst_key
;
3818 return NT_STATUS_NO_MEMORY
;
3820 for ( i
=0; i
<src
->num_keys
; i
++ ) {
3822 /* create a new instance of the printerkey in the destination
3823 printer_data object */
3825 new_key_index
= add_new_printer_key( dst
, src
->keys
[i
].name
);
3826 dst_key
= &dst
->keys
[new_key_index
].values
;
3828 src_key
= &src
->keys
[i
].values
;
3829 num_vals
= regval_ctr_numvals( src_key
);
3831 /* dup the printer entire printer key */
3833 for ( j
=0; j
<num_vals
; j
++ ) {
3834 regval_ctr_copyvalue( dst_key
, regval_ctr_specific_value(src_key
, j
) );
3838 return NT_STATUS_OK
;
3841 /****************************************************************************
3842 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
3844 ****************************************************************************/
3846 NT_PRINTER_INFO_LEVEL_2
* dup_printer_2( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL_2
*printer
)
3848 NT_PRINTER_INFO_LEVEL_2
*copy
;
3853 if ( !(copy
= (NT_PRINTER_INFO_LEVEL_2
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2
))) )
3856 memcpy( copy
, printer
, sizeof(NT_PRINTER_INFO_LEVEL_2
) );
3858 /* malloc()'d members copied here */
3860 copy
->devmode
= dup_nt_devicemode( printer
->devmode
);
3862 ZERO_STRUCT( copy
->data
);
3863 copy_printer_data( ©
->data
, &printer
->data
);
3865 /* this is talloc()'d; very ugly that we have a structure that
3866 is half malloc()'d and half talloc()'d but that is the way
3867 that the PRINTER_INFO stuff is written right now. --jerry */
3869 copy
->secdesc_buf
= dup_sec_desc_buf( ctx
, printer
->secdesc_buf
);
3874 /****************************************************************************
3875 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3876 ****************************************************************************/
3878 WERROR
get_a_printer( Printer_entry
*print_hnd
, NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
,
3879 const char *sharename
)
3882 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3886 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename
, (unsigned int)level
));
3890 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
3891 DEBUG(0,("get_a_printer: malloc fail.\n"));
3894 ZERO_STRUCTP(printer
);
3897 * check for cache first. A Printer handle cannot changed
3898 * to another printer object so we only check that the printer
3899 * is actually for a printer and that the printer_info pointer
3903 && (print_hnd
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)
3904 && print_hnd
->printer_info
)
3906 if ( !(printer
->info_2
= dup_printer_2(print_hnd
->ctx
, print_hnd
->printer_info
->info_2
)) ) {
3907 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
3913 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
3915 *pp_printer
= printer
;
3921 /* no cache for this handle; see if we can match one from another handle */
3924 result
= find_printer_in_print_hnd_cache(print_hnd
->ctx
, &printer
->info_2
, sharename
);
3926 /* fail to disk if we don't have it with any open handle */
3928 if ( !print_hnd
|| !W_ERROR_IS_OK(result
) )
3929 result
= get_a_printer_2(&printer
->info_2
, sharename
);
3931 /* we have a new printer now. Save it with this handle */
3933 if ( W_ERROR_IS_OK(result
) ) {
3934 dump_a_printer(*printer
, level
);
3936 /* save a copy in cache */
3937 if ( print_hnd
&& (print_hnd
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)) {
3938 if ( !print_hnd
->printer_info
)
3939 print_hnd
->printer_info
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
));
3941 if ( print_hnd
->printer_info
) {
3942 print_hnd
->printer_info
->info_2
= dup_printer_2(print_hnd
->ctx
, printer
->info_2
);
3944 /* don't fail the lookup just because the cache update failed */
3945 if ( !print_hnd
->printer_info
->info_2
)
3946 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
3949 *pp_printer
= printer
;
3957 result
=WERR_UNKNOWN_LEVEL
;
3961 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename
, (unsigned int)level
, dos_errstr(result
)));
3966 /****************************************************************************
3967 Deletes a NT_PRINTER_INFO_LEVEL struct.
3968 ****************************************************************************/
3970 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
3973 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
3975 DEBUG(104,("freeing a printer at level [%d]\n", level
));
3977 if (printer
== NULL
)
3982 if (printer
->info_2
!= NULL
) {
3983 free_nt_printer_info_level_2(&printer
->info_2
);
3994 SAFE_FREE(*pp_printer
);
3998 /****************************************************************************
3999 ****************************************************************************/
4000 uint32
add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4003 DEBUG(104,("adding a printer at level [%d]\n", level
));
4004 dump_a_printer_driver(driver
, level
);
4008 result
=add_a_printer_driver_3(driver
.info_3
);
4012 result
=add_a_printer_driver_6(driver
.info_6
);
4022 /****************************************************************************
4023 ****************************************************************************/
4025 WERROR
get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL
*driver
, uint32 level
,
4026 fstring drivername
, const char *architecture
, uint32 version
)
4032 /* Sometime we just want any version of the driver */
4034 if ( version
== DRIVER_ANY_VERSION
) {
4035 /* look for Win2k first and then for NT4 */
4036 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4039 if ( !W_ERROR_IS_OK(result
) ) {
4040 result
= get_a_printer_driver_3( &driver
->info_3
,
4041 drivername
, architecture
, 2 );
4044 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4045 architecture
, version
);
4054 if (W_ERROR_IS_OK(result
))
4055 dump_a_printer_driver(*driver
, level
);
4060 /****************************************************************************
4061 ****************************************************************************/
4062 uint32
free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4069 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
4070 if (driver
.info_3
!= NULL
)
4072 info3
=driver
.info_3
;
4073 SAFE_FREE(info3
->dependentfiles
);
4074 ZERO_STRUCTP(info3
);
4084 NT_PRINTER_DRIVER_INFO_LEVEL_6
*info6
;
4085 if (driver
.info_6
!= NULL
) {
4086 info6
=driver
.info_6
;
4087 SAFE_FREE(info6
->dependentfiles
);
4088 SAFE_FREE(info6
->previousnames
);
4089 ZERO_STRUCTP(info6
);
4105 /****************************************************************************
4106 Determine whether or not a particular driver is currently assigned
4108 ****************************************************************************/
4110 BOOL
printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
)
4113 int n_services
= lp_numservices();
4114 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4119 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4121 /* loop through the printers.tdb and check for the drivername */
4123 for (snum
=0; snum
<n_services
; snum
++) {
4124 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
4127 if ( !W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))) )
4130 if ( !StrCaseCmp(info_3
->name
, printer
->info_2
->drivername
) ) {
4131 free_a_printer( &printer
, 2 );
4135 free_a_printer( &printer
, 2 );
4138 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4140 /* report that the driver is not in use by default */
4146 /**********************************************************************
4147 Check to see if a ogiven file is in use by *info
4148 *********************************************************************/
4150 static BOOL
drv_file_in_use( char* file
, NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4157 if ( strequal(file
, info
->driverpath
) )
4160 if ( strequal(file
, info
->datafile
) )
4163 if ( strequal(file
, info
->configfile
) )
4166 if ( strequal(file
, info
->helpfile
) )
4169 /* see of there are any dependent files to examine */
4171 if ( !info
->dependentfiles
)
4174 while ( *info
->dependentfiles
[i
] ) {
4175 if ( strequal(file
, info
->dependentfiles
[i
]) )
4184 /**********************************************************************
4185 Utility function to remove the dependent file pointed to by the
4186 input parameter from the list
4187 *********************************************************************/
4189 static void trim_dependent_file( fstring files
[], int idx
)
4192 /* bump everything down a slot */
4194 while( *files
[idx
+1] ) {
4195 fstrcpy( files
[idx
], files
[idx
+1] );
4204 /**********************************************************************
4205 Check if any of the files used by src are also used by drv
4206 *********************************************************************/
4208 static BOOL
trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*src
,
4209 NT_PRINTER_DRIVER_INFO_LEVEL_3
*drv
)
4211 BOOL in_use
= False
;
4217 /* check each file. Remove it from the src structure if it overlaps */
4219 if ( drv_file_in_use(src
->driverpath
, drv
) ) {
4221 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driverpath
));
4222 fstrcpy( src
->driverpath
, "" );
4225 if ( drv_file_in_use(src
->datafile
, drv
) ) {
4227 DEBUG(10,("Removing datafile [%s] from list\n", src
->datafile
));
4228 fstrcpy( src
->datafile
, "" );
4231 if ( drv_file_in_use(src
->configfile
, drv
) ) {
4233 DEBUG(10,("Removing configfile [%s] from list\n", src
->configfile
));
4234 fstrcpy( src
->configfile
, "" );
4237 if ( drv_file_in_use(src
->helpfile
, drv
) ) {
4239 DEBUG(10,("Removing helpfile [%s] from list\n", src
->helpfile
));
4240 fstrcpy( src
->helpfile
, "" );
4243 /* are there any dependentfiles to examine? */
4245 if ( !src
->dependentfiles
)
4248 while ( *src
->dependentfiles
[i
] ) {
4249 if ( drv_file_in_use(src
->dependentfiles
[i
], drv
) ) {
4251 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependentfiles
[i
]));
4252 trim_dependent_file( src
->dependentfiles
, i
);
4260 /****************************************************************************
4261 Determine whether or not a particular driver files are currently being
4262 used by any other driver.
4264 Return value is True if any files were in use by other drivers
4265 and False otherwise.
4267 Upon return, *info has been modified to only contain the driver files
4268 which are not in use
4269 ****************************************************************************/
4271 BOOL
printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4276 fstring
*list
= NULL
;
4277 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4282 version
= info
->cversion
;
4284 /* loop over all driver versions */
4286 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4288 /* get the list of drivers */
4291 ndrivers
= get_ntdrivers(&list
, info
->environment
, version
);
4293 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4294 ndrivers
, info
->environment
, version
));
4296 /* check each driver for overlap in files */
4298 for (i
=0; i
<ndrivers
; i
++) {
4299 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
4301 ZERO_STRUCT(driver
);
4303 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, list
[i
], info
->environment
, version
)) ) {
4308 /* check if d2 uses any files from d1 */
4309 /* only if this is a different driver than the one being deleted */
4311 if ( !strequal(info
->name
, driver
.info_3
->name
) ) {
4312 if ( trim_overlap_drv_files(info
, driver
.info_3
) ) {
4313 free_a_printer_driver(driver
, 3);
4319 free_a_printer_driver(driver
, 3);
4324 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4326 driver
.info_3
= info
;
4328 if ( DEBUGLEVEL
>= 20 )
4329 dump_a_printer_driver( driver
, 3 );
4334 /****************************************************************************
4335 Actually delete the driver files. Make sure that
4336 printer_driver_files_in_use() return False before calling
4338 ****************************************************************************/
4340 static BOOL
delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
)
4344 connection_struct
*conn
;
4352 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3
->name
, info_3
->cversion
));
4355 * Connect to the print$ share under the same account as the
4356 * user connected to the rpc pipe. Note we must be root to
4360 null_pw
= data_blob( NULL
, 0 );
4361 fstrcpy(res_type
, "A:");
4363 conn
= make_connection_with_chdir( "print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
4367 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4371 /* Save who we are - we are temporarily becoming the connection user. */
4373 if ( !become_user(conn
, conn
->vuid
) ) {
4374 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4378 /* now delete the files; must strip the '\print$' string from
4381 if ( *info_3
->driverpath
) {
4382 if ( (s
= strchr( &info_3
->driverpath
[1], '\\' )) != NULL
) {
4383 DEBUG(10,("deleting driverfile [%s]\n", s
));
4384 unlink_internals(conn
, 0, s
);
4388 if ( *info_3
->configfile
) {
4389 if ( (s
= strchr( &info_3
->configfile
[1], '\\' )) != NULL
) {
4390 DEBUG(10,("deleting configfile [%s]\n", s
));
4391 unlink_internals(conn
, 0, s
);
4395 if ( *info_3
->datafile
) {
4396 if ( (s
= strchr( &info_3
->datafile
[1], '\\' )) != NULL
) {
4397 DEBUG(10,("deleting datafile [%s]\n", s
));
4398 unlink_internals(conn
, 0, s
);
4402 if ( *info_3
->helpfile
) {
4403 if ( (s
= strchr( &info_3
->helpfile
[1], '\\' )) != NULL
) {
4404 DEBUG(10,("deleting helpfile [%s]\n", s
));
4405 unlink_internals(conn
, 0, s
);
4409 /* check if we are done removing files */
4411 if ( info_3
->dependentfiles
) {
4412 while ( *info_3
->dependentfiles
[i
] ) {
4415 /* bypass the "\print$" portion of the path */
4417 if ( (file
= strchr( info_3
->dependentfiles
[i
]+1, '\\' )) != NULL
) {
4418 DEBUG(10,("deleting dependent file [%s]\n", file
));
4419 unlink_internals(conn
, 0, file
);
4431 /****************************************************************************
4432 Remove a printer driver from the TDB. This assumes that the the driver was
4433 previously looked up.
4434 ***************************************************************************/
4436 WERROR
delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
,
4437 uint32 version
, BOOL delete_files
)
4441 TDB_DATA kbuf
, dbuf
;
4442 NT_PRINTER_DRIVER_INFO_LEVEL ctr
;
4444 /* delete the tdb data first */
4446 arch
= get_short_archi(info_3
->environment
);
4447 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
,
4448 arch
, version
, info_3
->name
);
4450 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4451 key
, delete_files
? "TRUE" : "FALSE" ));
4453 ctr
.info_3
= info_3
;
4454 dump_a_printer_driver( ctr
, 3 );
4457 kbuf
.dsize
=strlen(key
)+1;
4459 /* check if the driver actually exists for this environment */
4461 dbuf
= tdb_fetch( tdb_drivers
, kbuf
);
4463 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key
));
4464 return WERR_UNKNOWN_PRINTER_DRIVER
;
4467 SAFE_FREE( dbuf
.dptr
);
4469 /* ok... the driver exists so the delete should return success */
4471 if (tdb_delete(tdb_drivers
, kbuf
) == -1) {
4472 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key
));
4473 return WERR_ACCESS_DENIED
;
4477 * now delete any associated files if delete_files == True
4478 * even if this part failes, we return succes because the
4479 * driver doesn not exist any more
4483 delete_driver_files( info_3
, user
);
4486 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key
));
4491 /****************************************************************************
4492 Store a security desc for a printer.
4493 ****************************************************************************/
4495 WERROR
nt_printing_setsec(const char *printername
, SEC_DESC_BUF
*secdesc_ctr
)
4497 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4498 SEC_DESC_BUF
*old_secdesc_ctr
= NULL
;
4500 TALLOC_CTX
*mem_ctx
= NULL
;
4504 mem_ctx
= talloc_init("nt_printing_setsec");
4505 if (mem_ctx
== NULL
)
4508 /* The old owner and group sids of the security descriptor are not
4509 present when new ACEs are added or removed by changing printer
4510 permissions through NT. If they are NULL in the new security
4511 descriptor then copy them over from the old one. */
4513 if (!secdesc_ctr
->sec
->owner_sid
|| !secdesc_ctr
->sec
->grp_sid
) {
4514 DOM_SID
*owner_sid
, *group_sid
;
4515 SEC_ACL
*dacl
, *sacl
;
4516 SEC_DESC
*psd
= NULL
;
4519 nt_printing_getsec(mem_ctx
, printername
, &old_secdesc_ctr
);
4521 /* Pick out correct owner and group sids */
4523 owner_sid
= secdesc_ctr
->sec
->owner_sid
?
4524 secdesc_ctr
->sec
->owner_sid
:
4525 old_secdesc_ctr
->sec
->owner_sid
;
4527 group_sid
= secdesc_ctr
->sec
->grp_sid
?
4528 secdesc_ctr
->sec
->grp_sid
:
4529 old_secdesc_ctr
->sec
->grp_sid
;
4531 dacl
= secdesc_ctr
->sec
->dacl
?
4532 secdesc_ctr
->sec
->dacl
:
4533 old_secdesc_ctr
->sec
->dacl
;
4535 sacl
= secdesc_ctr
->sec
->sacl
?
4536 secdesc_ctr
->sec
->sacl
:
4537 old_secdesc_ctr
->sec
->sacl
;
4539 /* Make a deep copy of the security descriptor */
4541 psd
= make_sec_desc(mem_ctx
, secdesc_ctr
->sec
->revision
,
4542 owner_sid
, group_sid
,
4547 new_secdesc_ctr
= make_sec_desc_buf(mem_ctx
, size
, psd
);
4550 if (!new_secdesc_ctr
) {
4551 new_secdesc_ctr
= secdesc_ctr
;
4554 /* Store the security descriptor in a tdb */
4556 prs_init(&ps
, (uint32
)sec_desc_size(new_secdesc_ctr
->sec
) +
4557 sizeof(SEC_DESC_BUF
), mem_ctx
, MARSHALL
);
4559 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr
,
4561 status
= WERR_BADFUNC
;
4565 slprintf(key
, sizeof(key
)-1, "SECDESC/%s", printername
);
4567 if (tdb_prs_store(tdb_printers
, key
, &ps
)==0) {
4570 DEBUG(1,("Failed to store secdesc for %s\n", printername
));
4571 status
= WERR_BADFUNC
;
4574 /* Free malloc'ed memory */
4580 talloc_destroy(mem_ctx
);
4584 /****************************************************************************
4585 Construct a default security descriptor buffer for a printer.
4586 ****************************************************************************/
4588 static SEC_DESC_BUF
*construct_default_printer_sdb(TALLOC_CTX
*ctx
)
4592 SEC_ACL
*psa
= NULL
;
4593 SEC_DESC_BUF
*sdb
= NULL
;
4594 SEC_DESC
*psd
= NULL
;
4598 /* Create an ACE where Everyone is allowed to print */
4600 init_sec_access(&sa
, PRINTER_ACE_PRINT
);
4601 init_sec_ace(&ace
[0], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4602 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4604 /* Make the security descriptor owned by the Administrators group
4605 on the PDC of the domain. */
4607 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
4608 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4611 /* Backup plan - make printer owned by admins.
4612 This should emulate a lanman printer as security
4613 settings can't be changed. */
4615 sid_copy(&owner_sid
, get_global_sam_sid());
4616 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4619 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
4620 init_sec_ace(&ace
[1], &owner_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4621 sa
, SEC_ACE_FLAG_OBJECT_INHERIT
|
4622 SEC_ACE_FLAG_INHERIT_ONLY
);
4624 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
4625 init_sec_ace(&ace
[2], &owner_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4626 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4628 /* The ACL revision number in rpc_secdesc.h differs from the one
4629 created by NT when setting ACE entries in printer
4630 descriptors. NT4 complains about the property being edited by a
4633 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, 3, ace
)) != NULL
) {
4634 psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
,
4636 NULL
, psa
, &sd_size
);
4640 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4644 sdb
= make_sec_desc_buf(ctx
, sd_size
, psd
);
4646 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4647 (unsigned int)sd_size
));
4652 /****************************************************************************
4653 Get a security desc for a printer.
4654 ****************************************************************************/
4656 BOOL
nt_printing_getsec(TALLOC_CTX
*ctx
, const char *printername
, SEC_DESC_BUF
**secdesc_ctr
)
4662 if (strlen(printername
) > 2 && (temp
= strchr(printername
+ 2, '\\'))) {
4663 printername
= temp
+ 1;
4666 /* Fetch security descriptor from tdb */
4668 slprintf(key
, sizeof(key
)-1, "SECDESC/%s", printername
);
4670 if (tdb_prs_fetch(tdb_printers
, key
, &ps
, ctx
)!=0 ||
4671 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1)) {
4673 DEBUG(4,("using default secdesc for %s\n", printername
));
4675 if (!(*secdesc_ctr
= construct_default_printer_sdb(ctx
))) {
4679 /* Save default security descriptor for later */
4681 prs_init(&ps
, (uint32
)sec_desc_size((*secdesc_ctr
)->sec
) +
4682 sizeof(SEC_DESC_BUF
), ctx
, MARSHALL
);
4684 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1))
4685 tdb_prs_store(tdb_printers
, key
, &ps
);
4692 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4693 this security descriptor has been created when winbindd was
4694 down. Take ownership of security descriptor. */
4696 if (sid_equal((*secdesc_ctr
)->sec
->owner_sid
, &global_sid_World
)) {
4699 /* Change sd owner to workgroup administrator */
4701 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
4702 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4703 SEC_DESC
*psd
= NULL
;
4708 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4710 psd
= make_sec_desc(ctx
, (*secdesc_ctr
)->sec
->revision
,
4712 (*secdesc_ctr
)->sec
->grp_sid
,
4713 (*secdesc_ctr
)->sec
->sacl
,
4714 (*secdesc_ctr
)->sec
->dacl
,
4717 new_secdesc_ctr
= make_sec_desc_buf(ctx
, size
, psd
);
4719 /* Swap with other one */
4721 *secdesc_ctr
= new_secdesc_ctr
;
4725 nt_printing_setsec(printername
, *secdesc_ctr
);
4729 if (DEBUGLEVEL
>= 10) {
4730 SEC_ACL
*the_acl
= (*secdesc_ctr
)->sec
->dacl
;
4733 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4734 printername
, the_acl
->num_aces
));
4736 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4739 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
4741 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str
,
4742 the_acl
->ace
[i
].type
, the_acl
->ace
[i
].flags
,
4743 the_acl
->ace
[i
].info
.mask
));
4753 1: level not implemented
4754 2: file doesn't exist
4755 3: can't allocate memory
4756 4: can't free memory
4757 5: non existant struct
4761 A printer and a printer driver are 2 different things.
4762 NT manages them separatelly, Samba does the same.
4763 Why ? Simply because it's easier and it makes sense !
4765 Now explanation: You have 3 printers behind your samba server,
4766 2 of them are the same make and model (laser A and B). But laser B
4767 has an 3000 sheet feeder and laser A doesn't such an option.
4768 Your third printer is an old dot-matrix model for the accounting :-).
4770 If the /usr/local/samba/lib directory (default dir), you will have
4771 5 files to describe all of this.
4773 3 files for the printers (1 by printer):
4776 NTprinter_accounting
4777 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4778 NTdriver_printer model X
4779 NTdriver_printer model Y
4781 jfm: I should use this comment for the text file to explain
4782 same thing for the forms BTW.
4783 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4787 /* Convert generic access rights to printer object specific access rights.
4788 It turns out that NT4 security descriptors use generic access rights and
4789 NT5 the object specific ones. */
4791 void map_printer_permissions(SEC_DESC
*sd
)
4795 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
4796 se_map_generic(&sd
->dacl
->ace
[i
].info
.mask
,
4797 &printer_generic_mapping
);
4801 /****************************************************************************
4802 Check a user has permissions to perform the given operation. We use the
4803 permission constants defined in include/rpc_spoolss.h to check the various
4804 actions we perform when checking printer access.
4806 PRINTER_ACCESS_ADMINISTER:
4807 print_queue_pause, print_queue_resume, update_printer_sec,
4808 update_printer, spoolss_addprinterex_level_2,
4809 _spoolss_setprinterdata
4814 JOB_ACCESS_ADMINISTER:
4815 print_job_delete, print_job_pause, print_job_resume,
4818 ****************************************************************************/
4819 BOOL
print_access_check(struct current_user
*user
, int snum
, int access_type
)
4821 SEC_DESC_BUF
*secdesc
= NULL
;
4822 uint32 access_granted
;
4826 TALLOC_CTX
*mem_ctx
= NULL
;
4827 extern struct current_user current_user
;
4829 /* If user is NULL then use the current_user structure */
4832 user
= ¤t_user
;
4834 /* Always allow root or printer admins to do anything */
4836 if (user
->uid
== 0 ||
4837 user_in_list(uidtoname(user
->uid
), lp_printer_admin(snum
), user
->groups
, user
->ngroups
)) {
4841 /* Get printer name */
4843 pname
= PRINTERNAME(snum
);
4845 if (!pname
|| !*pname
) {
4850 /* Get printer security descriptor */
4852 if(!(mem_ctx
= talloc_init("print_access_check"))) {
4857 nt_printing_getsec(mem_ctx
, pname
, &secdesc
);
4859 if (access_type
== JOB_ACCESS_ADMINISTER
) {
4860 SEC_DESC_BUF
*parent_secdesc
= secdesc
;
4862 /* Create a child security descriptor to check permissions
4863 against. This is because print jobs are child objects
4864 objects of a printer. */
4866 secdesc
= se_create_child_secdesc(mem_ctx
, parent_secdesc
->sec
, False
);
4868 /* Now this is the bit that really confuses me. The access
4869 type needs to be changed from JOB_ACCESS_ADMINISTER to
4870 PRINTER_ACCESS_ADMINISTER for this to work. Something
4871 to do with the child (job) object becoming like a
4874 access_type
= PRINTER_ACCESS_ADMINISTER
;
4879 map_printer_permissions(secdesc
->sec
);
4881 result
= se_access_check(secdesc
->sec
, user
->nt_user_token
, access_type
,
4882 &access_granted
, &status
);
4884 DEBUG(4, ("access check was %s\n", result
? "SUCCESS" : "FAILURE"));
4886 talloc_destroy(mem_ctx
);
4894 /****************************************************************************
4895 Check the time parameters allow a print operation.
4896 *****************************************************************************/
4898 BOOL
print_time_access_check(int snum
)
4900 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4902 time_t now
= time(NULL
);
4906 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))))
4909 if (printer
->info_2
->starttime
== 0 && printer
->info_2
->untiltime
== 0)
4913 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
4915 if (mins
>= printer
->info_2
->starttime
&& mins
<= printer
->info_2
->untiltime
)
4918 free_a_printer(&printer
, 2);