2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
6 * Copyright (C) Gerald Carter 2002-2003.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 extern DOM_SID global_sid_World
;
27 static TDB_CONTEXT
*tdb_forms
; /* used for forms files */
28 static TDB_CONTEXT
*tdb_drivers
; /* used for driver files */
29 static TDB_CONTEXT
*tdb_printers
; /* used for printers files */
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
42 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
44 /* Map generic permissions to printer object specific permissions */
46 GENERIC_MAPPING printer_generic_mapping
= {
53 STANDARD_MAPPING printer_std_mapping
= {
60 /* Map generic permissions to print server object specific permissions */
62 GENERIC_MAPPING printserver_generic_mapping
= {
69 STANDARD_MAPPING printserver_std_mapping
= {
76 /* We need one default form to support our default printer. Msoft adds the
77 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
78 array index). Letter is always first, so (for the current code) additions
79 always put things in the correct order. */
80 static const nt_forms_struct default_forms
[] = {
81 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
84 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
85 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
86 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
87 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
88 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
89 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
92 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
93 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
94 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
95 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
96 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
97 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
98 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
99 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
100 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
101 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
102 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
103 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
104 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
105 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
106 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
107 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
108 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
109 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
110 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
111 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
112 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
113 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
114 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
115 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
116 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
117 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
118 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
119 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
120 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
121 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
122 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
123 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
124 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
125 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
126 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
127 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
128 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
131 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
132 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
133 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
134 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
135 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
136 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
138 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
139 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
140 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
141 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
142 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
143 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
144 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
145 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
146 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
147 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
148 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
149 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
150 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
151 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
152 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
153 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
154 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
155 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
156 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
157 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
158 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
159 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
160 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
161 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
162 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
163 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
164 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
165 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
166 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
167 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
168 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
169 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
170 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
171 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
172 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
173 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
174 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
175 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
176 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
177 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
178 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
179 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
180 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
181 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
182 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
183 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
184 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
185 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
186 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
187 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
188 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
189 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
190 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
191 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
192 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
193 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
194 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
195 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
196 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
197 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
198 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
202 const char *long_archi
;
203 const char *short_archi
;
207 #define SPL_ARCH_WIN40 "WIN40"
208 #define SPL_ARCH_W32X86 "W32X86"
209 #define SPL_ARCH_W32MIPS "W32MIPS"
210 #define SPL_ARCH_W32ALPHA "W32ALPHA"
211 #define SPL_ARCH_W32PPC "W32PPC"
213 static const struct table_node archi_table
[]= {
215 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
216 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
217 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
218 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
219 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
223 static BOOL
upgrade_to_version_3(void)
225 TDB_DATA kbuf
, newkey
, dbuf
;
227 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
229 for (kbuf
= tdb_firstkey(tdb_drivers
); kbuf
.dptr
;
230 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
232 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
234 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) == 0) {
235 DEBUG(0,("upgrade_to_version_3:moving form\n"));
236 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
237 SAFE_FREE(dbuf
.dptr
);
238 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms
)));
241 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
242 SAFE_FREE(dbuf
.dptr
);
243 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
248 if (strncmp(kbuf
.dptr
, PRINTERS_PREFIX
, strlen(PRINTERS_PREFIX
)) == 0) {
249 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
250 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
251 SAFE_FREE(dbuf
.dptr
);
252 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers
)));
255 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
256 SAFE_FREE(dbuf
.dptr
);
257 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
262 if (strncmp(kbuf
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
)) == 0) {
263 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
264 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
265 SAFE_FREE(dbuf
.dptr
);
266 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers
)));
269 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
270 SAFE_FREE(dbuf
.dptr
);
271 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
276 SAFE_FREE(dbuf
.dptr
);
282 /****************************************************************************
283 Open the NT printing tdbs. Done once before fork().
284 ****************************************************************************/
286 BOOL
nt_printing_init(void)
288 static pid_t local_pid
;
289 const char *vstring
= "INFO/version";
291 if (tdb_drivers
&& tdb_printers
&& tdb_forms
&& local_pid
== sys_getpid())
295 tdb_close(tdb_drivers
);
296 tdb_drivers
= tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
298 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
299 lock_path("ntdrivers.tdb"), strerror(errno
) ));
304 tdb_close(tdb_printers
);
305 tdb_printers
= tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
307 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
308 lock_path("ntprinters.tdb"), strerror(errno
) ));
313 tdb_close(tdb_forms
);
314 tdb_forms
= tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
316 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
317 lock_path("ntforms.tdb"), strerror(errno
) ));
321 local_pid
= sys_getpid();
323 /* handle a Samba upgrade */
324 tdb_lock_bystring(tdb_drivers
, vstring
, 0);
328 /* Cope with byte-reversed older versions of the db. */
329 vers_id
= tdb_fetch_int32(tdb_drivers
, vstring
);
330 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_2
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_2
)) {
331 /* Written on a bigendian machine with old fetch_int code. Save as le. */
332 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
333 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION
);
334 vers_id
= NTDRIVERS_DATABASE_VERSION
;
337 if (vers_id
!= NTDRIVERS_DATABASE_VERSION
) {
339 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_1
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_1
)) {
340 if (!upgrade_to_version_3())
343 tdb_traverse(tdb_drivers
, tdb_traverse_delete_fn
, NULL
);
345 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION
);
348 tdb_unlock_bystring(tdb_drivers
, vstring
);
350 update_c_setprinter(True
);
353 * register callback to handle updating printers as new
354 * drivers are installed
357 message_register( MSG_PRINTER_DRVUPGRADE
, do_drv_upgrade_printer
);
360 * register callback to handle updating printer data
361 * when a driver is initialized
364 message_register( MSG_PRINTERDATA_INIT_RESET
, reset_all_printerdata
);
370 /*******************************************************************
371 tdb traversal function for counting printers.
372 ********************************************************************/
374 static int traverse_counting_printers(TDB_CONTEXT
*t
, TDB_DATA key
,
375 TDB_DATA data
, void *context
)
377 int *printer_count
= (int*)context
;
379 if (memcmp(PRINTERS_PREFIX
, key
.dptr
, sizeof(PRINTERS_PREFIX
)-1) == 0) {
381 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key
.dptr
, *printer_count
));
387 /*******************************************************************
388 Update the spooler global c_setprinter. This variable is initialized
389 when the parent smbd starts with the number of existing printers. It
390 is monotonically increased by the current number of printers *after*
391 each add or delete printer RPC. Only Microsoft knows why... JRR020119
392 ********************************************************************/
394 uint32
update_c_setprinter(BOOL initialize
)
397 int32 printer_count
= 0;
399 tdb_lock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
, 0);
401 /* Traverse the tdb, counting the printers */
402 tdb_traverse(tdb_printers
, traverse_counting_printers
, (void *)&printer_count
);
404 /* If initializing, set c_setprinter to current printers count
405 * otherwise, bump it by the current printer count
408 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
) + printer_count
;
410 c_setprinter
= printer_count
;
412 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter
));
413 tdb_store_int32(tdb_printers
, GLOBAL_C_SETPRINTER
, c_setprinter
);
415 tdb_unlock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
417 return (uint32
)c_setprinter
;
420 /*******************************************************************
421 Get the spooler global c_setprinter, accounting for initialization.
422 ********************************************************************/
424 uint32
get_c_setprinter(void)
426 int32 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
);
428 if (c_setprinter
== (int32
)-1)
429 c_setprinter
= update_c_setprinter(True
);
431 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter
));
433 return (uint32
)c_setprinter
;
436 /****************************************************************************
437 Get builtin form struct list.
438 ****************************************************************************/
440 int get_builtin_ntforms(nt_forms_struct
**list
)
442 *list
= (nt_forms_struct
*)memdup(&default_forms
[0], sizeof(default_forms
));
443 return sizeof(default_forms
) / sizeof(default_forms
[0]);
446 /****************************************************************************
447 get a builtin form struct
448 ****************************************************************************/
450 BOOL
get_a_builtin_ntform(UNISTR2
*uni_formname
,nt_forms_struct
*form
)
454 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
455 DEBUGADD(6,("Looking for builtin form %s \n", form_name
));
456 count
= sizeof(default_forms
) / sizeof(default_forms
[0]);
457 for (i
=0;i
<count
;i
++) {
458 if (strequal(form_name
,default_forms
[i
].name
)) {
459 DEBUGADD(6,("Found builtin form %s \n", form_name
));
460 memcpy(form
,&default_forms
[i
],sizeof(*form
));
468 /****************************************************************************
469 get a form struct list
470 ****************************************************************************/
471 int get_ntforms(nt_forms_struct
**list
)
473 TDB_DATA kbuf
, newkey
, dbuf
;
475 nt_forms_struct form
;
480 for (kbuf
= tdb_firstkey(tdb_forms
);
482 newkey
= tdb_nextkey(tdb_forms
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
)
484 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) != 0)
487 dbuf
= tdb_fetch(tdb_forms
, kbuf
);
491 fstrcpy(form
.name
, kbuf
.dptr
+strlen(FORMS_PREFIX
));
492 ret
= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dddddddd",
493 &i
, &form
.flag
, &form
.width
, &form
.length
, &form
.left
,
494 &form
.top
, &form
.right
, &form
.bottom
);
495 SAFE_FREE(dbuf
.dptr
);
496 if (ret
!= dbuf
.dsize
)
499 tl
= Realloc(*list
, sizeof(nt_forms_struct
)*(n
+1));
501 DEBUG(0,("get_ntforms: Realloc fail.\n"));
513 /****************************************************************************
514 write a form struct list
515 ****************************************************************************/
516 int write_ntforms(nt_forms_struct
**list
, int number
)
523 for (i
=0;i
<number
;i
++) {
524 /* save index, so list is rebuilt in correct order */
525 len
= tdb_pack(buf
, sizeof(buf
), "dddddddd",
526 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
527 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
529 if (len
> sizeof(buf
)) break;
530 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[i
].name
);
531 kbuf
.dsize
= strlen(key
)+1;
535 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) break;
541 /****************************************************************************
542 add a form struct at the end of the list
543 ****************************************************************************/
544 BOOL
add_a_form(nt_forms_struct
**list
, const FORM
*form
, int *count
)
552 * NT tries to add forms even when
553 * they are already in the base
554 * only update the values if already present
559 unistr2_to_ascii(form_name
, &form
->name
, sizeof(form_name
)-1);
560 for (n
=0; n
<*count
; n
++) {
561 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
562 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name
));
569 if((tl
=Realloc(*list
, (n
+1)*sizeof(nt_forms_struct
))) == NULL
) {
570 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
574 unistr2_to_ascii((*list
)[n
].name
, &form
->name
, sizeof((*list
)[n
].name
)-1);
578 (*list
)[n
].flag
=form
->flags
;
579 (*list
)[n
].width
=form
->size_x
;
580 (*list
)[n
].length
=form
->size_y
;
581 (*list
)[n
].left
=form
->left
;
582 (*list
)[n
].top
=form
->top
;
583 (*list
)[n
].right
=form
->right
;
584 (*list
)[n
].bottom
=form
->bottom
;
589 /****************************************************************************
590 Delete a named form struct.
591 ****************************************************************************/
593 BOOL
delete_a_form(nt_forms_struct
**list
, UNISTR2
*del_name
, int *count
, WERROR
*ret
)
602 unistr2_to_ascii(form_name
, del_name
, sizeof(form_name
)-1);
604 for (n
=0; n
<*count
; n
++) {
605 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
606 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name
));
612 DEBUG(10,("delete_a_form, [%s] not found\n", form_name
));
613 *ret
= WERR_INVALID_PARAM
;
617 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[n
].name
);
618 kbuf
.dsize
= strlen(key
)+1;
620 if (tdb_delete(tdb_forms
, kbuf
) != 0) {
628 /****************************************************************************
629 Update a form struct.
630 ****************************************************************************/
632 void update_a_form(nt_forms_struct
**list
, const FORM
*form
, int count
)
636 unistr2_to_ascii(form_name
, &(form
->name
), sizeof(form_name
)-1);
638 DEBUG(106, ("[%s]\n", form_name
));
639 for (n
=0; n
<count
; n
++) {
640 DEBUGADD(106, ("n [%d]:[%s]\n", n
, (*list
)[n
].name
));
641 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
)))
645 if (n
==count
) return;
647 (*list
)[n
].flag
=form
->flags
;
648 (*list
)[n
].width
=form
->size_x
;
649 (*list
)[n
].length
=form
->size_y
;
650 (*list
)[n
].left
=form
->left
;
651 (*list
)[n
].top
=form
->top
;
652 (*list
)[n
].right
=form
->right
;
653 (*list
)[n
].bottom
=form
->bottom
;
656 /****************************************************************************
657 Get the nt drivers list.
658 Traverse the database and look-up the matching names.
659 ****************************************************************************/
660 int get_ntdrivers(fstring
**list
, const char *architecture
, uint32 version
)
663 const char *short_archi
;
666 TDB_DATA kbuf
, newkey
;
668 short_archi
= get_short_archi(architecture
);
669 slprintf(key
, sizeof(key
)-1, "%s%s/%d/", DRIVERS_PREFIX
, short_archi
, version
);
671 for (kbuf
= tdb_firstkey(tdb_drivers
);
673 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
675 if (strncmp(kbuf
.dptr
, key
, strlen(key
)) != 0)
678 if((fl
= Realloc(*list
, sizeof(fstring
)*(total
+1))) == NULL
) {
679 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
684 fstrcpy((*list
)[total
], kbuf
.dptr
+strlen(key
));
691 /****************************************************************************
692 function to do the mapping between the long architecture name and
694 ****************************************************************************/
695 const char *get_short_archi(const char *long_archi
)
699 DEBUG(107,("Getting architecture dependant directory\n"));
702 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
703 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
705 if (archi_table
[i
].long_archi
==NULL
) {
706 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
710 /* this might be client code - but shouldn't this be an fstrcpy etc? */
713 DEBUGADD(108,("index: [%d]\n", i
));
714 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
715 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
717 return archi_table
[i
].short_archi
;
720 /****************************************************************************
721 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
722 There are two case to be covered here: PE (Portable Executable) and NE (New
723 Executable) files. Both files support the same INFO structure, but PE files
724 store the signature in unicode, and NE files store it as !unicode.
725 returns -1 on error, 1 on version info found, and 0 on no version info found.
726 ****************************************************************************/
728 static int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
734 if ((buf
=malloc(PE_HEADER_SIZE
)) == NULL
) {
735 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
736 fname
, PE_HEADER_SIZE
));
740 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
741 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
742 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
744 goto no_version_info
;
747 /* Is this really a DOS header? */
748 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
749 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
750 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
751 goto no_version_info
;
754 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
755 if (SMB_VFS_LSEEK(fsp
, fsp
->fd
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
756 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
758 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
759 goto no_version_info
;
762 if ((byte_count
= vfs_read_data(fsp
, buf
, PE_HEADER_SIZE
)) < PE_HEADER_SIZE
) {
763 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
765 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
766 goto no_version_info
;
769 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
770 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
772 int section_table_bytes
;
774 if (SVAL(buf
,PE_HEADER_MACHINE_OFFSET
) != PE_HEADER_MACHINE_I386
) {
775 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
776 fname
, SVAL(buf
,PE_HEADER_MACHINE_OFFSET
)));
777 /* At this point, we assume the file is in error. It still could be somthing
778 * else besides a PE file, but it unlikely at this point.
783 /* get the section table */
784 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
785 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
787 if ((buf
=malloc(section_table_bytes
)) == NULL
) {
788 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
789 fname
, section_table_bytes
));
793 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
794 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
799 /* Iterate the section table looking for the resource section ".rsrc" */
800 for (i
= 0; i
< num_sections
; i
++) {
801 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
803 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
804 int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
805 int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
808 if ((buf
=malloc(section_bytes
)) == NULL
) {
809 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
810 fname
, section_bytes
));
814 /* Seek to the start of the .rsrc section info */
815 if (SMB_VFS_LSEEK(fsp
, fsp
->fd
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
816 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
821 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
822 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
827 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
828 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
829 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
830 /* Align to next long address */
831 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
833 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
834 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
835 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
837 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
838 fname
, *major
, *minor
,
839 (*major
>>16)&0xffff, *major
&0xffff,
840 (*minor
>>16)&0xffff, *minor
&0xffff));
849 /* Version info not found, fall back to origin date/time */
850 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
854 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
855 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
856 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
857 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
858 /* At this point, we assume the file is in error. It still could be somthing
859 * else besides a NE file, but it unlikely at this point. */
863 /* Allocate a bit more space to speed up things */
865 if ((buf
=malloc(VS_NE_BUF_SIZE
)) == NULL
) {
866 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
867 fname
, PE_HEADER_SIZE
));
871 /* This is a HACK! I got tired of trying to sort through the messy
872 * 'NE' file format. If anyone wants to clean this up please have at
873 * it, but this works. 'NE' files will eventually fade away. JRR */
874 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
875 /* Cover case that should not occur in a well formed 'NE' .dll file */
876 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
878 for(i
=0; i
<byte_count
; i
++) {
879 /* Fast skip past data that can't possibly match */
880 if (buf
[i
] != 'V') continue;
882 /* Potential match data crosses buf boundry, move it to beginning
883 * of buf, and fill the buf with as much as it will hold. */
884 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
887 memcpy(buf
, &buf
[i
], byte_count
-i
);
888 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
889 (byte_count
-i
))) < 0) {
891 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
896 byte_count
= bc
+ (byte_count
- i
);
897 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
902 /* Check that the full signature string and the magic number that
903 * follows exist (not a perfect solution, but the chances that this
904 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
905 * twice, as it is simpler to read the code. */
906 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
907 /* Compute skip alignment to next long address */
908 int skip
= -(SMB_VFS_LSEEK(fsp
, fsp
->fd
, 0, SEEK_CUR
) - (byte_count
- i
) +
909 sizeof(VS_SIGNATURE
)) & 3;
910 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
912 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
913 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
914 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
915 fname
, *major
, *minor
,
916 (*major
>>16)&0xffff, *major
&0xffff,
917 (*minor
>>16)&0xffff, *minor
&0xffff));
924 /* Version info not found, fall back to origin date/time */
925 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
930 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
931 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
932 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
943 /****************************************************************************
944 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
945 share one or more files. During the MS installation process files are checked
946 to insure that only a newer version of a shared file is installed over an
947 older version. There are several possibilities for this comparison. If there
948 is no previous version, the new one is newer (obviously). If either file is
949 missing the version info structure, compare the creation date (on Unix use
950 the modification date). Otherwise chose the numerically larger version number.
951 ****************************************************************************/
953 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
955 BOOL use_version
= True
;
960 time_t new_create_time
;
964 time_t old_create_time
;
968 files_struct
*fsp
= NULL
;
970 SMB_STRUCT_STAT stat_buf
;
974 ZERO_STRUCT(stat_buf
);
975 new_create_time
= (time_t)0;
976 old_create_time
= (time_t)0;
978 /* Get file version info (if available) for previous file (if it exists) */
979 pstrcpy(filepath
, old_file
);
981 unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
983 fsp
= open_file_shared(conn
, filepath
, &stat_buf
,
984 SET_OPEN_MODE(DOS_OPEN_RDONLY
),
985 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
986 0, 0, &access_mode
, &action
);
988 /* Old file not found, so by definition new file is in fact newer */
989 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
994 int ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
995 if (ret
== -1) goto error_exit
;
998 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1000 use_version
= False
;
1001 if (SMB_VFS_FSTAT(fsp
, fsp
->fd
, &st
) == -1) goto error_exit
;
1002 old_create_time
= st
.st_mtime
;
1003 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time
));
1006 close_file(fsp
, True
);
1008 /* Get file version info (if available) for new file */
1009 pstrcpy(filepath
, new_file
);
1010 unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1012 fsp
= open_file_shared(conn
, filepath
, &stat_buf
,
1013 SET_OPEN_MODE(DOS_OPEN_RDONLY
),
1014 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1015 0, 0, &access_mode
, &action
);
1017 /* New file not found, this shouldn't occur if the caller did its job */
1018 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1023 int ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
1024 if (ret
== -1) goto error_exit
;
1027 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1029 use_version
= False
;
1030 if (SMB_VFS_FSTAT(fsp
, fsp
->fd
, &st
) == -1) goto error_exit
;
1031 new_create_time
= st
.st_mtime
;
1032 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time
));
1035 close_file(fsp
, True
);
1037 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
1038 /* Compare versions and choose the larger version number */
1039 if (new_major
> old_major
||
1040 (new_major
== old_major
&& new_minor
> old_minor
)) {
1042 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1046 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1051 /* Compare modification time/dates and choose the newest time/date */
1052 if (new_create_time
> old_create_time
) {
1053 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1057 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1064 close_file(fsp
, True
);
1068 /****************************************************************************
1069 Determine the correct cVersion associated with an architecture and driver
1070 ****************************************************************************/
1071 static uint32
get_correct_cversion(const char *architecture
, fstring driverpath_in
,
1072 struct current_user
*user
, WERROR
*perr
)
1081 files_struct
*fsp
= NULL
;
1084 connection_struct
*conn
;
1088 *perr
= WERR_INVALID_PARAM
;
1090 /* If architecture is Windows 95/98/ME, the version is always 0. */
1091 if (strcmp(architecture
, "WIN40") == 0) {
1092 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1098 * Connect to the print$ share under the same account as the user connected
1099 * to the rpc pipe. Note we must still be root to do this.
1102 /* Null password is ok - we are already an authenticated user... */
1103 null_pw
= data_blob(NULL
, 0);
1104 fstrcpy(res_type
, "A:");
1106 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1110 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1111 *perr
= ntstatus_to_werror(nt_status
);
1115 /* We are temporarily becoming the connection user. */
1116 if (!become_user(conn
, user
->vuid
)) {
1117 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1118 *perr
= WERR_ACCESS_DENIED
;
1122 /* Open the driver file (Portable Executable format) and determine the
1123 * deriver the cversion. */
1124 slprintf(driverpath
, sizeof(driverpath
)-1, "%s/%s", architecture
, driverpath_in
);
1126 unix_convert(driverpath
,conn
,NULL
,&bad_path
,&st
);
1128 fsp
= open_file_shared(conn
, driverpath
, &st
,
1129 SET_OPEN_MODE(DOS_OPEN_RDONLY
),
1130 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1131 0, 0, &access_mode
, &action
);
1133 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1134 driverpath
, errno
));
1135 *perr
= WERR_ACCESS_DENIED
;
1141 int ret
= get_file_version(fsp
, driverpath
, &major
, &minor
);
1142 if (ret
== -1) goto error_exit
;
1145 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath
));
1150 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1151 * for more details. Version in this case is not just the version of the
1152 * file, but the version in the sense of kernal mode (2) vs. user mode
1153 * (3) drivers. Other bits of the version fields are the version info.
1156 cversion
= major
& 0x0000ffff;
1158 case 2: /* WinNT drivers */
1159 case 3: /* Win2K drivers */
1163 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1164 driverpath
, cversion
));
1168 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1169 driverpath
, major
, minor
));
1172 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1173 driverpath
, cversion
));
1175 close_file(fsp
, True
);
1176 close_cnum(conn
, user
->vuid
);
1185 close_file(fsp
, True
);
1187 close_cnum(conn
, user
->vuid
);
1192 /****************************************************************************
1193 ****************************************************************************/
1194 static WERROR
clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
,
1195 struct current_user
*user
)
1197 const char *architecture
;
1203 /* clean up the driver name.
1204 * we can get .\driver.dll
1205 * or worse c:\windows\system\driver.dll !
1207 /* using an intermediate string to not have overlaping memcpy()'s */
1208 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1209 fstrcpy(new_name
, p
+1);
1210 fstrcpy(driver
->driverpath
, new_name
);
1213 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1214 fstrcpy(new_name
, p
+1);
1215 fstrcpy(driver
->datafile
, new_name
);
1218 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1219 fstrcpy(new_name
, p
+1);
1220 fstrcpy(driver
->configfile
, new_name
);
1223 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1224 fstrcpy(new_name
, p
+1);
1225 fstrcpy(driver
->helpfile
, new_name
);
1228 if (driver
->dependentfiles
) {
1229 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1230 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1231 fstrcpy(new_name
, p
+1);
1232 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1237 architecture
= get_short_archi(driver
->environment
);
1239 /* jfm:7/16/2000 the client always sends the cversion=0.
1240 * The server should check which version the driver is by reading
1241 * the PE header of driver->driverpath.
1243 * For Windows 95/98 the version is 0 (so the value sent is correct)
1244 * For Windows NT (the architecture doesn't matter)
1245 * NT 3.1: cversion=0
1246 * NT 3.5/3.51: cversion=1
1250 if ((driver
->cversion
= get_correct_cversion( architecture
,
1251 driver
->driverpath
, user
, &err
)) == -1)
1257 /****************************************************************************
1258 ****************************************************************************/
1259 static WERROR
clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
, struct current_user
*user
)
1261 const char *architecture
;
1267 /* clean up the driver name.
1268 * we can get .\driver.dll
1269 * or worse c:\windows\system\driver.dll !
1271 /* using an intermediate string to not have overlaping memcpy()'s */
1272 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1273 fstrcpy(new_name
, p
+1);
1274 fstrcpy(driver
->driverpath
, new_name
);
1277 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1278 fstrcpy(new_name
, p
+1);
1279 fstrcpy(driver
->datafile
, new_name
);
1282 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1283 fstrcpy(new_name
, p
+1);
1284 fstrcpy(driver
->configfile
, new_name
);
1287 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1288 fstrcpy(new_name
, p
+1);
1289 fstrcpy(driver
->helpfile
, new_name
);
1292 if (driver
->dependentfiles
) {
1293 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1294 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1295 fstrcpy(new_name
, p
+1);
1296 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1301 architecture
= get_short_archi(driver
->environment
);
1303 /* jfm:7/16/2000 the client always sends the cversion=0.
1304 * The server should check which version the driver is by reading
1305 * the PE header of driver->driverpath.
1307 * For Windows 95/98 the version is 0 (so the value sent is correct)
1308 * For Windows NT (the architecture doesn't matter)
1309 * NT 3.1: cversion=0
1310 * NT 3.5/3.51: cversion=1
1314 if ((driver
->version
= get_correct_cversion(architecture
, driver
->driverpath
, user
, &err
)) == -1)
1320 /****************************************************************************
1321 ****************************************************************************/
1322 WERROR
clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
,
1323 uint32 level
, struct current_user
*user
)
1328 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1329 driver
=driver_abstract
.info_3
;
1330 return clean_up_driver_struct_level_3(driver
, user
);
1334 NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
;
1335 driver
=driver_abstract
.info_6
;
1336 return clean_up_driver_struct_level_6(driver
, user
);
1339 return WERR_INVALID_PARAM
;
1343 /****************************************************************************
1344 This function sucks and should be replaced. JRA.
1345 ****************************************************************************/
1347 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*dst
, NT_PRINTER_DRIVER_INFO_LEVEL_6
*src
)
1349 dst
->cversion
= src
->version
;
1351 fstrcpy( dst
->name
, src
->name
);
1352 fstrcpy( dst
->environment
, src
->environment
);
1353 fstrcpy( dst
->driverpath
, src
->driverpath
);
1354 fstrcpy( dst
->datafile
, src
->datafile
);
1355 fstrcpy( dst
->configfile
, src
->configfile
);
1356 fstrcpy( dst
->helpfile
, src
->helpfile
);
1357 fstrcpy( dst
->monitorname
, src
->monitorname
);
1358 fstrcpy( dst
->defaultdatatype
, src
->defaultdatatype
);
1359 dst
->dependentfiles
= src
->dependentfiles
;
1362 #if 0 /* Debugging function */
1364 static char* ffmt(unsigned char *c
){
1366 static char ffmt_str
[17];
1368 for (i
=0; i
<16; i
++) {
1369 if ((c
[i
] < ' ') || (c
[i
] > '~'))
1380 /****************************************************************************
1381 ****************************************************************************/
1382 BOOL
move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
, uint32 level
,
1383 struct current_user
*user
, WERROR
*perr
)
1385 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1386 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver
;
1387 const char *architecture
;
1392 connection_struct
*conn
;
1400 memset(inbuf
, '\0', sizeof(inbuf
));
1401 memset(outbuf
, '\0', sizeof(outbuf
));
1405 driver
=driver_abstract
.info_3
;
1406 else if (level
==6) {
1407 convert_level_6_to_level3(&converted_driver
, driver_abstract
.info_6
);
1408 driver
= &converted_driver
;
1410 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level
));
1414 architecture
= get_short_archi(driver
->environment
);
1417 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1418 * Note we must be root to do this.
1421 null_pw
= data_blob(NULL
, 0);
1422 fstrcpy(res_type
, "A:");
1424 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1428 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1429 *perr
= ntstatus_to_werror(nt_status
);
1434 * Save who we are - we are temporarily becoming the connection user.
1437 if (!become_user(conn
, conn
->vuid
)) {
1438 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1443 * make the directories version and version\driver_name
1444 * under the architecture directory.
1446 DEBUG(5,("Creating first directory\n"));
1447 slprintf(new_dir
, sizeof(new_dir
)-1, "%s/%d", architecture
, driver
->cversion
);
1448 mkdir_internal(conn
, new_dir
);
1450 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1451 * listed for this driver which has already been moved, skip it (note:
1452 * drivers may list the same file name several times. Then check if the
1453 * file already exists in archi\cversion\, if so, check that the version
1454 * info (or time stamps if version info is unavailable) is newer (or the
1455 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1456 * Otherwise, delete the file.
1458 * If a file is not moved to archi\cversion\ because of an error, all the
1459 * rest of the 'unmoved' driver files are removed from archi\. If one or
1460 * more of the driver's files was already moved to archi\cversion\, it
1461 * potentially leaves the driver in a partially updated state. Version
1462 * trauma will most likely occur if an client attempts to use any printer
1463 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1464 * done is appropriate... later JRR
1467 DEBUG(5,("Moving files now !\n"));
1469 if (driver
->driverpath
&& strlen(driver
->driverpath
)) {
1470 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->driverpath
);
1471 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->driverpath
);
1472 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1474 status
= rename_internals(conn
, new_name
, old_name
, True
);
1475 if (!NT_STATUS_IS_OK(status
)) {
1476 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1477 new_name
, old_name
));
1478 *perr
= ntstatus_to_werror(status
);
1479 unlink_internals(conn
, 0, new_name
);
1484 unlink_internals(conn
, 0, new_name
);
1487 if (driver
->datafile
&& strlen(driver
->datafile
)) {
1488 if (!strequal(driver
->datafile
, driver
->driverpath
)) {
1489 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->datafile
);
1490 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->datafile
);
1491 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1493 status
= rename_internals(conn
, new_name
, old_name
, True
);
1494 if (!NT_STATUS_IS_OK(status
)) {
1495 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1496 new_name
, old_name
));
1497 *perr
= ntstatus_to_werror(status
);
1498 unlink_internals(conn
, 0, new_name
);
1503 unlink_internals(conn
, 0, new_name
);
1507 if (driver
->configfile
&& strlen(driver
->configfile
)) {
1508 if (!strequal(driver
->configfile
, driver
->driverpath
) &&
1509 !strequal(driver
->configfile
, driver
->datafile
)) {
1510 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->configfile
);
1511 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->configfile
);
1512 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1514 status
= rename_internals(conn
, new_name
, old_name
, True
);
1515 if (!NT_STATUS_IS_OK(status
)) {
1516 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1517 new_name
, old_name
));
1518 *perr
= ntstatus_to_werror(status
);
1519 unlink_internals(conn
, 0, new_name
);
1524 unlink_internals(conn
, 0, new_name
);
1528 if (driver
->helpfile
&& strlen(driver
->helpfile
)) {
1529 if (!strequal(driver
->helpfile
, driver
->driverpath
) &&
1530 !strequal(driver
->helpfile
, driver
->datafile
) &&
1531 !strequal(driver
->helpfile
, driver
->configfile
)) {
1532 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->helpfile
);
1533 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->helpfile
);
1534 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1536 status
= rename_internals(conn
, new_name
, old_name
, True
);
1537 if (!NT_STATUS_IS_OK(status
)) {
1538 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1539 new_name
, old_name
));
1540 *perr
= ntstatus_to_werror(status
);
1541 unlink_internals(conn
, 0, new_name
);
1546 unlink_internals(conn
, 0, new_name
);
1550 if (driver
->dependentfiles
) {
1551 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1552 if (!strequal(driver
->dependentfiles
[i
], driver
->driverpath
) &&
1553 !strequal(driver
->dependentfiles
[i
], driver
->datafile
) &&
1554 !strequal(driver
->dependentfiles
[i
], driver
->configfile
) &&
1555 !strequal(driver
->dependentfiles
[i
], driver
->helpfile
)) {
1557 for (j
=0; j
< i
; j
++) {
1558 if (strequal(driver
->dependentfiles
[i
], driver
->dependentfiles
[j
])) {
1563 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->dependentfiles
[i
]);
1564 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->dependentfiles
[i
]);
1565 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1567 status
= rename_internals(conn
, new_name
, old_name
, True
);
1568 if (!NT_STATUS_IS_OK(status
)) {
1569 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1570 new_name
, old_name
));
1571 *perr
= ntstatus_to_werror(status
);
1572 unlink_internals(conn
, 0, new_name
);
1577 unlink_internals(conn
, 0, new_name
);
1583 close_cnum(conn
, user
->vuid
);
1586 return ver
== -1 ? False
: True
;
1589 /****************************************************************************
1590 ****************************************************************************/
1591 static uint32
add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
)
1594 const char *architecture
;
1600 TDB_DATA kbuf
, dbuf
;
1602 architecture
= get_short_archi(driver
->environment
);
1604 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1605 * \\server is added in the rpc server layer.
1606 * It does make sense to NOT store the server's name in the printer TDB.
1609 slprintf(directory
, sizeof(directory
)-1, "\\print$\\%s\\%d\\", architecture
, driver
->cversion
);
1611 /* .inf files do not always list a file for each of the four standard files.
1612 * Don't prepend a path to a null filename, or client claims:
1613 * "The server on which the printer resides does not have a suitable
1614 * <printer driver name> printer driver installed. Click OK if you
1615 * wish to install the driver on your local machine."
1617 if (strlen(driver
->driverpath
)) {
1618 fstrcpy(temp_name
, driver
->driverpath
);
1619 slprintf(driver
->driverpath
, sizeof(driver
->driverpath
)-1, "%s%s", directory
, temp_name
);
1622 if (strlen(driver
->datafile
)) {
1623 fstrcpy(temp_name
, driver
->datafile
);
1624 slprintf(driver
->datafile
, sizeof(driver
->datafile
)-1, "%s%s", directory
, temp_name
);
1627 if (strlen(driver
->configfile
)) {
1628 fstrcpy(temp_name
, driver
->configfile
);
1629 slprintf(driver
->configfile
, sizeof(driver
->configfile
)-1, "%s%s", directory
, temp_name
);
1632 if (strlen(driver
->helpfile
)) {
1633 fstrcpy(temp_name
, driver
->helpfile
);
1634 slprintf(driver
->helpfile
, sizeof(driver
->helpfile
)-1, "%s%s", directory
, temp_name
);
1637 if (driver
->dependentfiles
) {
1638 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1639 fstrcpy(temp_name
, driver
->dependentfiles
[i
]);
1640 slprintf(driver
->dependentfiles
[i
], sizeof(driver
->dependentfiles
[i
])-1, "%s%s", directory
, temp_name
);
1644 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, driver
->cversion
, driver
->name
);
1646 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key
));
1653 len
+= tdb_pack(buf
+len
, buflen
-len
, "dffffffff",
1656 driver
->environment
,
1661 driver
->monitorname
,
1662 driver
->defaultdatatype
);
1664 if (driver
->dependentfiles
) {
1665 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1666 len
+= tdb_pack(buf
+len
, buflen
-len
, "f",
1667 driver
->dependentfiles
[i
]);
1671 if (len
!= buflen
) {
1674 tb
= (char *)Realloc(buf
, len
);
1676 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1687 kbuf
.dsize
= strlen(key
)+1;
1691 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
1695 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key
));
1701 /****************************************************************************
1702 ****************************************************************************/
1703 static uint32
add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
)
1705 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3
;
1708 info3
.cversion
= driver
->version
;
1709 fstrcpy(info3
.name
,driver
->name
);
1710 fstrcpy(info3
.environment
,driver
->environment
);
1711 fstrcpy(info3
.driverpath
,driver
->driverpath
);
1712 fstrcpy(info3
.datafile
,driver
->datafile
);
1713 fstrcpy(info3
.configfile
,driver
->configfile
);
1714 fstrcpy(info3
.helpfile
,driver
->helpfile
);
1715 fstrcpy(info3
.monitorname
,driver
->monitorname
);
1716 fstrcpy(info3
.defaultdatatype
,driver
->defaultdatatype
);
1717 info3
.dependentfiles
= driver
->dependentfiles
;
1719 return add_a_printer_driver_3(&info3
);
1723 /****************************************************************************
1724 ****************************************************************************/
1725 static WERROR
get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, const char *driver
, const char *arch
)
1727 NT_PRINTER_DRIVER_INFO_LEVEL_3 info
;
1731 fstrcpy(info
.name
, driver
);
1732 fstrcpy(info
.defaultdatatype
, "RAW");
1734 fstrcpy(info
.driverpath
, "");
1735 fstrcpy(info
.datafile
, "");
1736 fstrcpy(info
.configfile
, "");
1737 fstrcpy(info
.helpfile
, "");
1739 if ((info
.dependentfiles
=(fstring
*)malloc(2*sizeof(fstring
))) == NULL
)
1742 memset(info
.dependentfiles
, '\0', 2*sizeof(fstring
));
1743 fstrcpy(info
.dependentfiles
[0], "");
1745 *info_ptr
= memdup(&info
, sizeof(info
));
1750 /****************************************************************************
1751 ****************************************************************************/
1752 static WERROR
get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, fstring drivername
, const char *arch
, uint32 version
)
1754 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver
;
1755 TDB_DATA kbuf
, dbuf
;
1756 const char *architecture
;
1761 ZERO_STRUCT(driver
);
1763 architecture
= get_short_archi(arch
);
1765 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1767 if ( strcmp( architecture
, SPL_ARCH_WIN40
) == 0 )
1770 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX
, architecture
, version
, drivername
));
1772 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, version
, drivername
);
1775 kbuf
.dsize
= strlen(key
)+1;
1777 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
1779 return WERR_UNKNOWN_PRINTER_DRIVER
;
1781 len
+= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dffffffff",
1790 driver
.defaultdatatype
);
1793 while (len
< dbuf
.dsize
) {
1796 tddfs
= (fstring
*)Realloc(driver
.dependentfiles
,
1797 sizeof(fstring
)*(i
+2));
1798 if (tddfs
== NULL
) {
1799 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1802 else driver
.dependentfiles
= tddfs
;
1804 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "f",
1805 &driver
.dependentfiles
[i
]);
1809 if (driver
.dependentfiles
!= NULL
)
1810 fstrcpy(driver
.dependentfiles
[i
], "");
1812 SAFE_FREE(dbuf
.dptr
);
1814 if (len
!= dbuf
.dsize
) {
1815 SAFE_FREE(driver
.dependentfiles
);
1817 return get_a_printer_driver_3_default(info_ptr
, drivername
, arch
);
1820 *info_ptr
= (NT_PRINTER_DRIVER_INFO_LEVEL_3
*)memdup(&driver
, sizeof(driver
));
1825 /****************************************************************************
1826 Debugging function, dump at level 6 the struct in the logs.
1827 ****************************************************************************/
1829 static uint32
dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
1832 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
1835 DEBUG(20,("Dumping printer driver at level [%d]\n", level
));
1841 if (driver
.info_3
== NULL
)
1844 info3
=driver
.info_3
;
1846 DEBUGADD(20,("version:[%d]\n", info3
->cversion
));
1847 DEBUGADD(20,("name:[%s]\n", info3
->name
));
1848 DEBUGADD(20,("environment:[%s]\n", info3
->environment
));
1849 DEBUGADD(20,("driverpath:[%s]\n", info3
->driverpath
));
1850 DEBUGADD(20,("datafile:[%s]\n", info3
->datafile
));
1851 DEBUGADD(20,("configfile:[%s]\n", info3
->configfile
));
1852 DEBUGADD(20,("helpfile:[%s]\n", info3
->helpfile
));
1853 DEBUGADD(20,("monitorname:[%s]\n", info3
->monitorname
));
1854 DEBUGADD(20,("defaultdatatype:[%s]\n", info3
->defaultdatatype
));
1856 for (i
=0; info3
->dependentfiles
&&
1857 *info3
->dependentfiles
[i
]; i
++) {
1858 DEBUGADD(20,("dependentfile:[%s]\n",
1859 info3
->dependentfiles
[i
]));
1866 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level
));
1874 /****************************************************************************
1875 ****************************************************************************/
1876 int pack_devicemode(NT_DEVICEMODE
*nt_devmode
, char *buf
, int buflen
)
1880 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", nt_devmode
);
1885 len
+= tdb_pack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1886 nt_devmode
->devicename
,
1887 nt_devmode
->formname
,
1889 nt_devmode
->specversion
,
1890 nt_devmode
->driverversion
,
1892 nt_devmode
->driverextra
,
1893 nt_devmode
->orientation
,
1894 nt_devmode
->papersize
,
1895 nt_devmode
->paperlength
,
1896 nt_devmode
->paperwidth
,
1899 nt_devmode
->defaultsource
,
1900 nt_devmode
->printquality
,
1903 nt_devmode
->yresolution
,
1904 nt_devmode
->ttoption
,
1905 nt_devmode
->collate
,
1906 nt_devmode
->logpixels
,
1909 nt_devmode
->bitsperpel
,
1910 nt_devmode
->pelswidth
,
1911 nt_devmode
->pelsheight
,
1912 nt_devmode
->displayflags
,
1913 nt_devmode
->displayfrequency
,
1914 nt_devmode
->icmmethod
,
1915 nt_devmode
->icmintent
,
1916 nt_devmode
->mediatype
,
1917 nt_devmode
->dithertype
,
1918 nt_devmode
->reserved1
,
1919 nt_devmode
->reserved2
,
1920 nt_devmode
->panningwidth
,
1921 nt_devmode
->panningheight
,
1922 nt_devmode
->private);
1925 if (nt_devmode
->private) {
1926 len
+= tdb_pack(buf
+len
, buflen
-len
, "B",
1927 nt_devmode
->driverextra
,
1928 nt_devmode
->private);
1931 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode
->formname
));
1936 /****************************************************************************
1937 Pack all values in all printer keys
1938 ***************************************************************************/
1940 static int pack_values(NT_PRINTER_DATA
*data
, char *buf
, int buflen
)
1944 REGISTRY_VALUE
*val
;
1945 REGVAL_CTR
*val_ctr
;
1952 /* loop over all keys */
1954 for ( i
=0; i
<data
->num_keys
; i
++ ) {
1955 val_ctr
= &data
->keys
[i
].values
;
1956 num_values
= regval_ctr_numvals( val_ctr
);
1958 /* loop over all values */
1960 for ( j
=0; j
<num_values
; j
++ ) {
1961 /* pathname should be stored as <key>\<value> */
1963 val
= regval_ctr_specific_value( val_ctr
, j
);
1964 pstrcpy( path
, data
->keys
[i
].name
);
1965 pstrcat( path
, "\\" );
1966 pstrcat( path
, regval_name(val
) );
1968 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
1973 regval_data_p(val
) );
1980 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", NULL
);
1986 /****************************************************************************
1987 Delete a printer - this just deletes the printer info file, any open
1988 handles are not affected.
1989 ****************************************************************************/
1991 uint32
del_a_printer(char *sharename
)
1996 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
1999 kbuf
.dsize
=strlen(key
)+1;
2001 tdb_delete(tdb_printers
, kbuf
);
2005 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
2006 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
**, const char* sharename
);
2007 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**);
2008 /****************************************************************************
2009 ****************************************************************************/
2010 static WERROR
update_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
)
2016 TDB_DATA kbuf
, dbuf
;
2019 * in addprinter: no servername and the printer is the name
2020 * in setprinter: servername is \\server
2021 * and printer is \\server\\printer
2023 * Samba manages only local printers.
2024 * we currently don't support things like path=\\other_server\printer
2027 if (info
->servername
[0]!='\0') {
2028 trim_string(info
->printername
, info
->servername
, NULL
);
2029 trim_char(info
->printername
, '\\', '\0');
2030 info
->servername
[0]='\0';
2034 * JFM: one day I'll forget.
2035 * below that's info->portname because that's the SAMBA sharename
2036 * and I made NT 'thinks' it's the portname
2037 * the info->sharename is the thing you can name when you add a printer
2038 * that's the short-name when you create shared printer for 95/98
2039 * So I've made a limitation in SAMBA: you can only have 1 printer model
2040 * behind a SAMBA share.
2048 len
+= tdb_pack(buf
+len
, buflen
-len
, "dddddddddddfffffPfffff",
2051 info
->default_priority
,
2068 info
->printprocessor
,
2072 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
2074 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
2076 if (buflen
!= len
) {
2079 tb
= (char *)Realloc(buf
, len
);
2081 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2091 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, info
->sharename
);
2094 kbuf
.dsize
= strlen(key
)+1;
2098 ret
= (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) == 0? WERR_OK
: WERR_NOMEM
);
2101 if (!W_ERROR_IS_OK(ret
))
2102 DEBUG(8, ("error updating printer to tdb on disk\n"));
2106 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2107 info
->sharename
, info
->drivername
, info
->portname
, len
));
2113 /****************************************************************************
2114 Malloc and return an NT devicemode.
2115 ****************************************************************************/
2117 NT_DEVICEMODE
*construct_nt_devicemode(const fstring default_devicename
)
2120 char adevice
[MAXDEVICENAME
];
2121 NT_DEVICEMODE
*nt_devmode
= (NT_DEVICEMODE
*)malloc(sizeof(NT_DEVICEMODE
));
2123 if (nt_devmode
== NULL
) {
2124 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2128 ZERO_STRUCTP(nt_devmode
);
2130 safe_strcpy(adevice
, default_devicename
, sizeof(adevice
)-1);
2131 fstrcpy(nt_devmode
->devicename
, adevice
);
2133 fstrcpy(nt_devmode
->formname
, "Letter");
2135 nt_devmode
->specversion
= 0x0401;
2136 nt_devmode
->driverversion
= 0x0400;
2137 nt_devmode
->size
= 0x00DC;
2138 nt_devmode
->driverextra
= 0x0000;
2139 nt_devmode
->fields
= FORMNAME
| TTOPTION
| PRINTQUALITY
|
2140 DEFAULTSOURCE
| COPIES
| SCALE
|
2141 PAPERSIZE
| ORIENTATION
;
2142 nt_devmode
->orientation
= 1;
2143 nt_devmode
->papersize
= PAPER_LETTER
;
2144 nt_devmode
->paperlength
= 0;
2145 nt_devmode
->paperwidth
= 0;
2146 nt_devmode
->scale
= 0x64;
2147 nt_devmode
->copies
= 1;
2148 nt_devmode
->defaultsource
= BIN_FORMSOURCE
;
2149 nt_devmode
->printquality
= RES_HIGH
; /* 0x0258 */
2150 nt_devmode
->color
= COLOR_MONOCHROME
;
2151 nt_devmode
->duplex
= DUP_SIMPLEX
;
2152 nt_devmode
->yresolution
= 0;
2153 nt_devmode
->ttoption
= TT_SUBDEV
;
2154 nt_devmode
->collate
= COLLATE_FALSE
;
2155 nt_devmode
->icmmethod
= 0;
2156 nt_devmode
->icmintent
= 0;
2157 nt_devmode
->mediatype
= 0;
2158 nt_devmode
->dithertype
= 0;
2160 /* non utilisés par un driver d'imprimante */
2161 nt_devmode
->logpixels
= 0;
2162 nt_devmode
->bitsperpel
= 0;
2163 nt_devmode
->pelswidth
= 0;
2164 nt_devmode
->pelsheight
= 0;
2165 nt_devmode
->displayflags
= 0;
2166 nt_devmode
->displayfrequency
= 0;
2167 nt_devmode
->reserved1
= 0;
2168 nt_devmode
->reserved2
= 0;
2169 nt_devmode
->panningwidth
= 0;
2170 nt_devmode
->panningheight
= 0;
2172 nt_devmode
->private = NULL
;
2176 /****************************************************************************
2177 Deepcopy an NT devicemode.
2178 ****************************************************************************/
2180 NT_DEVICEMODE
*dup_nt_devicemode(NT_DEVICEMODE
*nt_devicemode
)
2182 NT_DEVICEMODE
*new_nt_devicemode
= NULL
;
2184 if ( !nt_devicemode
)
2187 if ((new_nt_devicemode
= (NT_DEVICEMODE
*)memdup(nt_devicemode
, sizeof(NT_DEVICEMODE
))) == NULL
) {
2188 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2192 new_nt_devicemode
->private = NULL
;
2193 if (nt_devicemode
->private != NULL
) {
2194 if ((new_nt_devicemode
->private = memdup(nt_devicemode
->private, nt_devicemode
->driverextra
)) == NULL
) {
2195 SAFE_FREE(new_nt_devicemode
);
2196 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2201 return new_nt_devicemode
;
2204 /****************************************************************************
2205 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2206 ****************************************************************************/
2208 void free_nt_devicemode(NT_DEVICEMODE
**devmode_ptr
)
2210 NT_DEVICEMODE
*nt_devmode
= *devmode_ptr
;
2212 if(nt_devmode
== NULL
)
2215 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2217 SAFE_FREE(nt_devmode
->private);
2218 SAFE_FREE(*devmode_ptr
);
2221 /****************************************************************************
2222 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2223 ****************************************************************************/
2224 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
)
2226 NT_PRINTER_INFO_LEVEL_2
*info
= *info_ptr
;
2227 NT_PRINTER_DATA
*data
;
2233 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2235 free_nt_devicemode(&info
->devmode
);
2237 /* clean up all registry keys */
2240 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2241 SAFE_FREE( data
->keys
[i
].name
);
2242 regval_ctr_destroy( &data
->keys
[i
].values
);
2244 SAFE_FREE( data
->keys
);
2246 /* finally the top level structure */
2248 SAFE_FREE( *info_ptr
);
2252 /****************************************************************************
2253 ****************************************************************************/
2254 int unpack_devicemode(NT_DEVICEMODE
**nt_devmode
, char *buf
, int buflen
)
2258 NT_DEVICEMODE devmode
;
2260 ZERO_STRUCT(devmode
);
2262 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2264 if (!*nt_devmode
) return len
;
2266 len
+= tdb_unpack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2270 &devmode
.specversion
,
2271 &devmode
.driverversion
,
2273 &devmode
.driverextra
,
2274 &devmode
.orientation
,
2276 &devmode
.paperlength
,
2277 &devmode
.paperwidth
,
2280 &devmode
.defaultsource
,
2281 &devmode
.printquality
,
2284 &devmode
.yresolution
,
2290 &devmode
.bitsperpel
,
2292 &devmode
.pelsheight
,
2293 &devmode
.displayflags
,
2294 &devmode
.displayfrequency
,
2298 &devmode
.dithertype
,
2301 &devmode
.panningwidth
,
2302 &devmode
.panningheight
,
2305 if (devmode
.private) {
2306 /* the len in tdb_unpack is an int value and
2307 * devmode.driverextra is only a short
2309 len
+= tdb_unpack(buf
+len
, buflen
-len
, "B", &extra_len
, &devmode
.private);
2310 devmode
.driverextra
=(uint16
)extra_len
;
2312 /* check to catch an invalid TDB entry so we don't segfault */
2313 if (devmode
.driverextra
== 0) {
2314 devmode
.private = NULL
;
2318 *nt_devmode
= (NT_DEVICEMODE
*)memdup(&devmode
, sizeof(devmode
));
2320 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode
.devicename
, devmode
.formname
));
2321 if (devmode
.private)
2322 DEBUG(8,("with a private section of %d bytes\n", devmode
.driverextra
));
2327 /****************************************************************************
2328 Allocate and initialize a new slot.
2329 ***************************************************************************/
2331 static int add_new_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2336 if ( !data
|| !name
)
2339 /* allocate another slot in the NT_PRINTER_KEY array */
2341 d
= Realloc( data
->keys
, sizeof(NT_PRINTER_KEY
)*(data
->num_keys
+1) );
2345 key_index
= data
->num_keys
;
2347 /* initialze new key */
2350 data
->keys
[key_index
].name
= strdup( name
);
2352 ZERO_STRUCTP( &data
->keys
[key_index
].values
);
2354 regval_ctr_init( &data
->keys
[key_index
].values
);
2356 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name
));
2361 /****************************************************************************
2362 search for a registry key name in the existing printer data
2363 ***************************************************************************/
2365 int lookup_printerkey( NT_PRINTER_DATA
*data
, const char *name
)
2370 if ( !data
|| !name
)
2373 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name
));
2375 /* loop over all existing keys */
2377 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2378 if ( strequal(data
->keys
[i
].name
, name
) ) {
2379 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name
));
2389 /****************************************************************************
2390 ***************************************************************************/
2392 uint32
get_printer_subkeys( NT_PRINTER_DATA
*data
, const char* key
, fstring
**subkeys
)
2396 int num_subkeys
= 0;
2398 fstring
*ptr
, *subkeys_ptr
= NULL
;
2404 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2405 if ( StrnCaseCmp(data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2406 /* match sure it is a subkey and not the key itself */
2408 key_len
= strlen( key
);
2409 if ( strlen(data
->keys
[i
].name
) == key_len
)
2412 /* get subkey path */
2414 p
= data
->keys
[i
].name
+ key_len
;
2417 fstrcpy( subkeyname
, p
);
2418 if ( (p
= strchr( subkeyname
, '\\' )) )
2421 /* don't add a key more than once */
2423 for ( j
=0; j
<num_subkeys
; j
++ ) {
2424 if ( strequal( subkeys_ptr
[j
], subkeyname
) )
2428 if ( j
!= num_subkeys
)
2431 /* found a match, so allocate space and copy the name */
2433 if ( !(ptr
= Realloc( subkeys_ptr
, (num_subkeys
+2)*sizeof(fstring
))) ) {
2434 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2436 SAFE_FREE( subkeys
);
2441 fstrcpy( subkeys_ptr
[num_subkeys
], subkeyname
);
2447 /* tag of the end */
2450 fstrcpy(subkeys_ptr
[num_subkeys
], "" );
2452 *subkeys
= subkeys_ptr
;
2458 static void map_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2461 smb_ucs2_t conv_str
[1024];
2464 regval_ctr_delvalue(ctr
, val_name
);
2465 str_size
= push_ucs2(NULL
, conv_str
, sz
, sizeof(conv_str
),
2466 STR_TERMINATE
| STR_NOALIGN
);
2467 regval_ctr_addvalue(ctr
, val_name
, REG_SZ
,
2468 (char *) conv_str
, str_size
);
2471 static void map_dword_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2474 regval_ctr_delvalue(ctr
, val_name
);
2475 regval_ctr_addvalue(ctr
, val_name
, REG_DWORD
,
2476 (char *) &dword
, sizeof(dword
));
2479 static void map_bool_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2482 uint8 bin_bool
= (b
? 1 : 0);
2483 regval_ctr_delvalue(ctr
, val_name
);
2484 regval_ctr_addvalue(ctr
, val_name
, REG_BINARY
,
2485 (char *) &bin_bool
, sizeof(bin_bool
));
2488 static void map_single_multi_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2489 const char *multi_sz
)
2491 smb_ucs2_t
*conv_strs
= NULL
;
2494 /* a multi-sz has to have a null string terminator, i.e., the last
2495 string must be followed by two nulls */
2496 str_size
= (strlen(multi_sz
) + 2) * sizeof(smb_ucs2_t
);
2497 conv_strs
= calloc(str_size
, 1);
2499 push_ucs2(NULL
, conv_strs
, multi_sz
, str_size
,
2500 STR_TERMINATE
| STR_NOALIGN
);
2502 regval_ctr_delvalue(ctr
, val_name
);
2503 regval_ctr_addvalue(ctr
, val_name
, REG_MULTI_SZ
,
2504 (char *) conv_strs
, str_size
);
2505 safe_free(conv_strs
);
2509 /****************************************************************************
2510 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2512 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2513 * @return BOOL indicating success or failure
2514 ***************************************************************************/
2516 static BOOL
map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2
*info2
)
2518 REGVAL_CTR
*ctr
= NULL
;
2520 char *allocated_string
= NULL
;
2521 const char *ascii_str
;
2524 if ((i
= lookup_printerkey(&info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2525 i
= add_new_printer_key(&info2
->data
, SPOOL_DSSPOOLER_KEY
);
2526 ctr
= &info2
->data
.keys
[i
].values
;
2528 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTERNAME
, info2
->sharename
);
2529 map_sz_into_ctr(ctr
, SPOOL_REG_SHORTSERVERNAME
, global_myname());
2531 get_myfullname(longname
);
2532 map_sz_into_ctr(ctr
, SPOOL_REG_SERVERNAME
, longname
);
2534 asprintf(&allocated_string
, "\\\\%s\\%s", longname
, info2
->sharename
);
2535 map_sz_into_ctr(ctr
, SPOOL_REG_UNCNAME
, allocated_string
);
2536 SAFE_FREE(allocated_string
);
2538 map_dword_into_ctr(ctr
, SPOOL_REG_VERSIONNUMBER
, 4);
2539 map_sz_into_ctr(ctr
, SPOOL_REG_DRIVERNAME
, info2
->drivername
);
2540 map_sz_into_ctr(ctr
, SPOOL_REG_LOCATION
, info2
->location
);
2541 map_sz_into_ctr(ctr
, SPOOL_REG_DESCRIPTION
, info2
->comment
);
2542 map_single_multi_sz_into_ctr(ctr
, SPOOL_REG_PORTNAME
, info2
->portname
);
2543 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSEPARATORFILE
, info2
->sepfile
);
2544 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTSTARTTIME
, info2
->starttime
);
2545 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTENDTIME
, info2
->untiltime
);
2546 map_dword_into_ctr(ctr
, SPOOL_REG_PRIORITY
, info2
->priority
);
2548 map_bool_into_ctr(ctr
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
2549 (info2
->attributes
&
2550 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
2552 switch (info2
->attributes
& 0x3) {
2554 ascii_str
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
2557 ascii_str
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
2560 ascii_str
= SPOOL_REGVAL_PRINTDIRECT
;
2563 ascii_str
= "unknown";
2565 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSPOOLING
, ascii_str
);
2570 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2
*info2
, GUID guid
)
2573 REGVAL_CTR
*ctr
=NULL
;
2575 /* find the DsSpooler key */
2576 if ((i
= lookup_printerkey(&info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2577 i
= add_new_printer_key(&info2
->data
, SPOOL_DSSPOOLER_KEY
);
2578 ctr
= &info2
->data
.keys
[i
].values
;
2580 regval_ctr_delvalue(ctr
, "objectGUID");
2581 regval_ctr_addvalue(ctr
, "objectGUID", REG_BINARY
,
2582 (char *) &guid
, sizeof(GUID
));
2585 static WERROR
publish_it(NT_PRINTER_INFO_LEVEL
*printer
)
2588 TALLOC_CTX
*ctx
= talloc_init("publish_it");
2589 ADS_MODLIST mods
= ads_init_mods(ctx
);
2590 char *prt_dn
= NULL
, *srv_dn
, *srv_cn_0
;
2591 char *srv_dn_utf8
, **srv_cn_utf8
;
2594 const char *attrs
[] = {"objectGUID", NULL
};
2596 WERROR win_rc
= WERR_OK
;
2599 /* set the DsSpooler info and attributes */
2600 if (!(map_nt_printer_info2_to_dsspooler(printer
->info_2
)))
2602 printer
->info_2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
2603 win_rc
= mod_a_printer(*printer
, 2);
2604 if (!W_ERROR_IS_OK(win_rc
)) {
2605 DEBUG(3, ("err %d saving data\n",
2606 W_ERROR_V(win_rc
)));
2610 /* Build the ads mods */
2611 get_local_printer_publishing_data(ctx
, &mods
,
2612 &printer
->info_2
->data
);
2613 ads_mod_str(ctx
, &mods
, SPOOL_REG_PRINTERNAME
,
2614 printer
->info_2
->sharename
);
2616 /* initial ads structure */
2618 ads
= ads_init(NULL
, NULL
, NULL
);
2620 DEBUG(3, ("ads_init() failed\n"));
2621 return WERR_SERVER_UNAVAILABLE
;
2623 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
2624 SAFE_FREE(ads
->auth
.password
);
2625 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
2628 /* ads_connect() will find the DC for us */
2629 ads_rc
= ads_connect(ads
);
2630 if (!ADS_ERR_OK(ads_rc
)) {
2631 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
2633 return WERR_ACCESS_DENIED
;
2636 /* figure out where to publish */
2637 ads_find_machine_acct(ads
, &res
, global_myname());
2639 /* We use ldap_get_dn here as we need the answer
2640 * in utf8 to call ldap_explode_dn(). JRA. */
2642 srv_dn_utf8
= ldap_get_dn(ads
->ld
, res
);
2645 return WERR_SERVER_UNAVAILABLE
;
2647 ads_msgfree(ads
, res
);
2648 srv_cn_utf8
= ldap_explode_dn(srv_dn_utf8
, 1);
2650 ldap_memfree(srv_dn_utf8
);
2652 return WERR_SERVER_UNAVAILABLE
;
2654 /* Now convert to CH_UNIX. */
2655 if (pull_utf8_allocate((void **) &srv_dn
, srv_dn_utf8
) == (size_t)-1) {
2656 ldap_memfree(srv_dn_utf8
);
2657 ldap_memfree(srv_cn_utf8
);
2659 return WERR_SERVER_UNAVAILABLE
;
2661 if (pull_utf8_allocate((void **) &srv_cn_0
, srv_cn_utf8
[0]) == (size_t)-1) {
2662 ldap_memfree(srv_dn_utf8
);
2663 ldap_memfree(srv_cn_utf8
);
2666 return WERR_SERVER_UNAVAILABLE
;
2669 ldap_memfree(srv_dn_utf8
);
2670 ldap_memfree(srv_cn_utf8
);
2672 asprintf(&prt_dn
, "cn=%s-%s,%s", srv_cn_0
,
2673 printer
->info_2
->sharename
, srv_dn
);
2676 SAFE_FREE(srv_cn_0
);
2679 ads_rc
= ads_add_printer_entry(ads
, prt_dn
, ctx
, &mods
);
2680 if (LDAP_ALREADY_EXISTS
== ads_rc
.err
.rc
)
2681 ads_rc
= ads_mod_printer_entry(ads
, prt_dn
, ctx
,&mods
);
2683 /* retreive the guid and store it locally */
2684 if (ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
2685 ads_memfree(ads
, prt_dn
);
2686 ads_pull_guid(ads
, res
, &guid
);
2687 ads_msgfree(ads
, res
);
2688 store_printer_guid(printer
->info_2
, guid
);
2689 win_rc
= mod_a_printer(*printer
, 2);
2698 WERROR
unpublish_it(NT_PRINTER_INFO_LEVEL
*printer
)
2703 char *prt_dn
= NULL
;
2706 printer
->info_2
->attributes
^= PRINTER_ATTRIBUTE_PUBLISHED
;
2707 win_rc
= mod_a_printer(*printer
, 2);
2708 if (!W_ERROR_IS_OK(win_rc
)) {
2709 DEBUG(3, ("err %d saving data\n",
2710 W_ERROR_V(win_rc
)));
2714 ads
= ads_init(NULL
, NULL
, NULL
);
2716 DEBUG(3, ("ads_init() failed\n"));
2717 return WERR_SERVER_UNAVAILABLE
;
2719 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
2720 SAFE_FREE(ads
->auth
.password
);
2721 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
2724 /* ads_connect() will find the DC for us */
2725 ads_rc
= ads_connect(ads
);
2726 if (!ADS_ERR_OK(ads_rc
)) {
2727 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
2729 return WERR_ACCESS_DENIED
;
2732 /* remove the printer from the directory */
2733 ads_rc
= ads_find_printer_on_server(ads
, &res
,
2734 printer
->info_2
->sharename
, global_myname());
2735 if (ADS_ERR_OK(ads_rc
) && ads_count_replies(ads
, res
)) {
2736 prt_dn
= ads_get_dn(ads
, res
);
2737 ads_msgfree(ads
, res
);
2738 ads_rc
= ads_del_dn(ads
, prt_dn
);
2739 ads_memfree(ads
, prt_dn
);
2746 /****************************************************************************
2747 * Publish a printer in the directory
2749 * @param snum describing printer service
2750 * @return WERROR indicating status of publishing
2751 ***************************************************************************/
2753 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
2755 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2758 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
2759 if (!W_ERROR_IS_OK(win_rc
))
2763 case SPOOL_DS_PUBLISH
:
2764 case SPOOL_DS_UPDATE
:
2765 win_rc
= publish_it(printer
);
2767 case SPOOL_DS_UNPUBLISH
:
2768 win_rc
= unpublish_it(printer
);
2771 win_rc
= WERR_NOT_SUPPORTED
;
2775 free_a_printer(&printer
, 2);
2779 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
, GUID
*guid
)
2781 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2783 REGISTRY_VALUE
*guid_val
;
2788 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
2789 if (!W_ERROR_IS_OK(win_rc
))
2792 if (!(printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
))
2795 if ((i
= lookup_printerkey(&printer
->info_2
->data
,
2796 SPOOL_DSSPOOLER_KEY
)) < 0)
2799 if (!(ctr
= &printer
->info_2
->data
.keys
[i
].values
)) {
2803 if (!(guid_val
= regval_ctr_getvalue(ctr
, "objectGUID"))) {
2807 if (regval_size(guid_val
) == sizeof(GUID
))
2808 memcpy(guid
, regval_data_p(guid_val
), sizeof(GUID
));
2814 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
2818 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
, GUID
*guid
)
2823 /****************************************************************************
2824 ***************************************************************************/
2826 WERROR
delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
)
2828 NT_PRINTER_DATA
*data
;
2830 int removed_keys
= 0;
2834 empty_slot
= data
->num_keys
;
2837 return WERR_INVALID_PARAM
;
2839 /* remove all keys */
2841 if ( !strlen(key
) ) {
2842 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2843 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2844 data
->keys
[i
].name
));
2846 SAFE_FREE( data
->keys
[i
].name
);
2847 regval_ctr_destroy( &data
->keys
[i
].values
);
2850 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2853 SAFE_FREE( data
->keys
);
2854 ZERO_STRUCTP( data
);
2859 /* remove a specific key (and all subkeys) */
2861 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2862 if ( StrnCaseCmp( data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2863 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2864 data
->keys
[i
].name
));
2866 SAFE_FREE( data
->keys
[i
].name
);
2867 regval_ctr_destroy( &data
->keys
[i
].values
);
2869 /* mark the slot as empty */
2871 ZERO_STRUCTP( &data
->keys
[i
] );
2875 /* find the first empty slot */
2877 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2878 if ( !data
->keys
[i
].name
) {
2885 if ( i
== data
->num_keys
)
2886 /* nothing was removed */
2887 return WERR_INVALID_PARAM
;
2889 /* move everything down */
2891 for ( i
=empty_slot
+1; i
<data
->num_keys
; i
++ ) {
2892 if ( data
->keys
[i
].name
) {
2893 memcpy( &data
->keys
[empty_slot
], &data
->keys
[i
], sizeof(NT_PRINTER_KEY
) );
2894 ZERO_STRUCTP( &data
->keys
[i
] );
2902 data
->num_keys
-= removed_keys
;
2904 /* sanity check to see if anything is left */
2906 if ( !data
->num_keys
) {
2907 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2
->printername
));
2909 SAFE_FREE( data
->keys
);
2910 ZERO_STRUCTP( data
);
2916 /****************************************************************************
2917 ***************************************************************************/
2919 WERROR
delete_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
2921 WERROR result
= WERR_OK
;
2924 /* we must have names on non-zero length */
2926 if ( !key
|| !*key
|| !value
|| !*value
)
2927 return WERR_INVALID_NAME
;
2929 /* find the printer key first */
2931 key_index
= lookup_printerkey( &p2
->data
, key
);
2932 if ( key_index
== -1 )
2935 /* make sure the value exists so we can return the correct error code */
2937 if ( !regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
) )
2938 return WERR_BADFILE
;
2940 regval_ctr_delvalue( &p2
->data
.keys
[key_index
].values
, value
);
2942 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2948 /****************************************************************************
2949 ***************************************************************************/
2951 WERROR
add_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
,
2952 uint32 type
, uint8
*data
, int real_len
)
2954 WERROR result
= WERR_OK
;
2957 /* we must have names on non-zero length */
2959 if ( !key
|| !*key
|| !value
|| !*value
)
2960 return WERR_INVALID_NAME
;
2962 /* find the printer key first */
2964 key_index
= lookup_printerkey( &p2
->data
, key
);
2965 if ( key_index
== -1 )
2966 key_index
= add_new_printer_key( &p2
->data
, key
);
2968 if ( key_index
== -1 )
2971 regval_ctr_addvalue( &p2
->data
.keys
[key_index
].values
, value
,
2972 type
, (const char *)data
, real_len
);
2974 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
2975 key
, value
, type
, real_len
));
2980 /****************************************************************************
2981 ***************************************************************************/
2983 REGISTRY_VALUE
* get_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
2987 if ( (key_index
= lookup_printerkey( &p2
->data
, key
)) == -1 )
2990 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
2993 return regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
);
2996 /****************************************************************************
2997 Unpack a list of registry values frem the TDB
2998 ***************************************************************************/
3000 static int unpack_values(NT_PRINTER_DATA
*printer_data
, char *buf
, int buflen
)
3004 pstring string
, valuename
, keyname
;
3008 REGISTRY_VALUE
*regval_p
;
3011 /* add the "PrinterDriverData" key first for performance reasons */
3013 add_new_printer_key( printer_data
, SPOOL_PRINTERDATA_KEY
);
3015 /* loop and unpack the rest of the registry values */
3019 /* check to see if there are any more registry values */
3021 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", ®val_p
);
3025 /* unpack the next regval */
3027 len
+= tdb_unpack(buf
+len
, buflen
-len
, "fdB",
3034 * break of the keyname from the value name.
3035 * Should only be one '\' in the string returned.
3038 str
= strrchr( string
, '\\');
3040 /* Put in "PrinterDriverData" is no key specified */
3043 pstrcpy( keyname
, SPOOL_PRINTERDATA_KEY
);
3044 pstrcpy( valuename
, string
);
3048 pstrcpy( keyname
, string
);
3049 pstrcpy( valuename
, str
+1 );
3052 /* see if we need a new key */
3054 if ( (key_index
=lookup_printerkey( printer_data
, keyname
)) == -1 )
3055 key_index
= add_new_printer_key( printer_data
, keyname
);
3057 if ( key_index
== -1 ) {
3058 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3063 /* add the new value */
3065 regval_ctr_addvalue( &printer_data
->keys
[key_index
].values
, valuename
, type
, (const char *)data_p
, size
);
3067 SAFE_FREE(data_p
); /* 'B' option to tdbpack does a malloc() */
3069 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname
, valuename
, size
));
3075 /****************************************************************************
3076 ***************************************************************************/
3078 static void map_to_os2_driver(fstring drivername
)
3080 static BOOL initialised
=False
;
3081 static fstring last_from
,last_to
;
3082 char *mapfile
= lp_os2_driver_map();
3083 char **lines
= NULL
;
3087 if (!strlen(drivername
))
3094 *last_from
= *last_to
= 0;
3098 if (strequal(drivername
,last_from
)) {
3099 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,last_to
));
3100 fstrcpy(drivername
,last_to
);
3104 lines
= file_lines_load(mapfile
, &numlines
);
3105 if (numlines
== 0) {
3106 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile
));
3110 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
3112 for( i
= 0; i
< numlines
; i
++) {
3113 char *nt_name
= lines
[i
];
3114 char *os2_name
= strchr(nt_name
,'=');
3121 while (isspace(*nt_name
))
3124 if (!*nt_name
|| strchr("#;",*nt_name
))
3128 int l
= strlen(nt_name
);
3129 while (l
&& isspace(nt_name
[l
-1])) {
3135 while (isspace(*os2_name
))
3139 int l
= strlen(os2_name
);
3140 while (l
&& isspace(os2_name
[l
-1])) {
3146 if (strequal(nt_name
,drivername
)) {
3147 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername
,os2_name
));
3148 fstrcpy(last_from
,drivername
);
3149 fstrcpy(last_to
,os2_name
);
3150 fstrcpy(drivername
,os2_name
);
3151 file_lines_free(lines
);
3156 file_lines_free(lines
);
3159 /****************************************************************************
3160 Get a default printer info 2 struct.
3161 ****************************************************************************/
3162 static WERROR
get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, const char *sharename
)
3165 NT_PRINTER_INFO_LEVEL_2 info
;
3169 snum
= lp_servicenumber(sharename
);
3171 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", get_called_name());
3172 slprintf(info
.printername
, sizeof(info
.printername
)-1, "\\\\%s\\%s",
3173 get_called_name(), sharename
);
3174 fstrcpy(info
.sharename
, sharename
);
3175 fstrcpy(info
.portname
, SAMBA_PRINTER_PORT_NAME
);
3177 /* by setting the driver name to an empty string, a local NT admin
3178 can now run the **local** APW to install a local printer driver
3179 for a Samba shared printer in 2.2. Without this, drivers **must** be
3180 installed on the Samba server for NT clients --jerry */
3181 #if 0 /* JERRY --do not uncomment-- */
3182 if (!*info
.drivername
)
3183 fstrcpy(info
.drivername
, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3187 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info
.drivername
));
3189 pstrcpy(info
.comment
, "");
3190 fstrcpy(info
.printprocessor
, "winprint");
3191 fstrcpy(info
.datatype
, "RAW");
3193 info
.attributes
= PRINTER_ATTRIBUTE_SAMBA
;
3195 info
.starttime
= 0; /* Minutes since 12:00am GMT */
3196 info
.untiltime
= 0; /* Minutes since 12:00am GMT */
3198 info
.default_priority
= 1;
3199 info
.setuptime
= (uint32
)time(NULL
);
3202 * I changed this as I think it is better to have a generic
3203 * DEVMODE than to crash Win2k explorer.exe --jerry
3204 * See the HP Deskjet 990c Win2k drivers for an example.
3206 * However the default devmode appears to cause problems
3207 * with the HP CLJ 8500 PCL driver. Hence the addition of
3208 * the "default devmode" parameter --jerry 22/01/2002
3211 if (lp_default_devmode(snum
)) {
3212 if ((info
.devmode
= construct_nt_devicemode(info
.printername
)) == NULL
)
3216 info
.devmode
= NULL
;
3219 /* This will get the current RPC talloc context, but we should be
3220 passing this as a parameter... fixme... JRA ! */
3222 if (!nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
))
3225 *info_ptr
= (NT_PRINTER_INFO_LEVEL_2
*)memdup(&info
, sizeof(info
));
3227 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3235 free_nt_devicemode(&info
.devmode
);
3236 return WERR_ACCESS_DENIED
;
3239 /****************************************************************************
3240 ****************************************************************************/
3241 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, const char *sharename
)
3244 NT_PRINTER_INFO_LEVEL_2 info
;
3246 TDB_DATA kbuf
, dbuf
;
3247 fstring printername
;
3248 char adevice
[MAXDEVICENAME
];
3252 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
3255 kbuf
.dsize
= strlen(key
)+1;
3257 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
3259 return get_a_printer_2_default(info_ptr
, sharename
);
3261 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "dddddddddddfffffPfffff",
3264 &info
.default_priority
,
3281 info
.printprocessor
,
3285 /* Samba has to have shared raw drivers. */
3286 info
.attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
3288 /* Restore the stripped strings. */
3289 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", get_called_name());
3290 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", get_called_name(),
3292 fstrcpy(info
.printername
, printername
);
3294 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3297 * Some client drivers freak out if there is a NULL devmode
3298 * (probably the driver is not checking before accessing
3299 * the devmode pointer) --jerry
3301 * See comments in get_a_printer_2_default()
3304 if (lp_default_devmode(lp_servicenumber(sharename
)) && !info
.devmode
) {
3305 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3307 info
.devmode
= construct_nt_devicemode(printername
);
3310 safe_strcpy(adevice
, info
.printername
, sizeof(adevice
)-1);
3312 fstrcpy(info
.devmode
->devicename
, adevice
);
3315 len
+= unpack_values( &info
.data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3317 /* This will get the current RPC talloc context, but we should be
3318 passing this as a parameter... fixme... JRA ! */
3320 nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
);
3322 /* Fix for OS/2 drivers. */
3324 if (get_remote_arch() == RA_OS2
)
3325 map_to_os2_driver(info
.drivername
);
3327 SAFE_FREE(dbuf
.dptr
);
3328 *info_ptr
=memdup(&info
, sizeof(info
));
3330 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3331 sharename
, info
.printername
, info
.drivername
));
3336 /****************************************************************************
3337 Debugging function, dump at level 6 the struct in the logs.
3338 ****************************************************************************/
3339 static uint32
dump_a_printer(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3342 NT_PRINTER_INFO_LEVEL_2
*info2
;
3344 DEBUG(106,("Dumping printer at level [%d]\n", level
));
3349 if (printer
.info_2
== NULL
)
3353 info2
=printer
.info_2
;
3355 DEBUGADD(106,("attributes:[%d]\n", info2
->attributes
));
3356 DEBUGADD(106,("priority:[%d]\n", info2
->priority
));
3357 DEBUGADD(106,("default_priority:[%d]\n", info2
->default_priority
));
3358 DEBUGADD(106,("starttime:[%d]\n", info2
->starttime
));
3359 DEBUGADD(106,("untiltime:[%d]\n", info2
->untiltime
));
3360 DEBUGADD(106,("status:[%d]\n", info2
->status
));
3361 DEBUGADD(106,("cjobs:[%d]\n", info2
->cjobs
));
3362 DEBUGADD(106,("averageppm:[%d]\n", info2
->averageppm
));
3363 DEBUGADD(106,("changeid:[%d]\n", info2
->changeid
));
3364 DEBUGADD(106,("c_setprinter:[%d]\n", info2
->c_setprinter
));
3365 DEBUGADD(106,("setuptime:[%d]\n", info2
->setuptime
));
3367 DEBUGADD(106,("servername:[%s]\n", info2
->servername
));
3368 DEBUGADD(106,("printername:[%s]\n", info2
->printername
));
3369 DEBUGADD(106,("sharename:[%s]\n", info2
->sharename
));
3370 DEBUGADD(106,("portname:[%s]\n", info2
->portname
));
3371 DEBUGADD(106,("drivername:[%s]\n", info2
->drivername
));
3372 DEBUGADD(106,("comment:[%s]\n", info2
->comment
));
3373 DEBUGADD(106,("location:[%s]\n", info2
->location
));
3374 DEBUGADD(106,("sepfile:[%s]\n", info2
->sepfile
));
3375 DEBUGADD(106,("printprocessor:[%s]\n", info2
->printprocessor
));
3376 DEBUGADD(106,("datatype:[%s]\n", info2
->datatype
));
3377 DEBUGADD(106,("parameters:[%s]\n", info2
->parameters
));
3383 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level
));
3391 /****************************************************************************
3392 Update the changeid time.
3393 This is SO NASTY as some drivers need this to change, others need it
3394 static. This value will change every second, and I must hope that this
3395 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3397 ****************************************************************************/
3399 static uint32
rev_changeid(void)
3403 get_process_uptime(&tv
);
3406 /* Return changeid as msec since spooler restart */
3407 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
3410 * This setting seems to work well but is too untested
3411 * to replace the above calculation. Left in for experiementation
3412 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3414 return tv
.tv_sec
* 10 + tv
.tv_usec
/ 100000;
3419 * The function below are the high level ones.
3420 * only those ones must be called from the spoolss code.
3424 /****************************************************************************
3425 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3426 ****************************************************************************/
3428 WERROR
mod_a_printer(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3432 dump_a_printer(printer
, level
);
3435 * invalidate cache for all open handles to this printer.
3436 * cache for a given handle will be updated on the next
3440 invalidate_printer_hnd_cache( printer
.info_2
->sharename
);
3446 * Update the changestamp. Emperical tests show that the
3447 * ChangeID is always updated,but c_setprinter is
3448 * global spooler variable (not per printer).
3451 /* ChangeID **must** be increasing over the lifetime
3452 of client's spoolss service in order for the
3453 client's cache to show updates */
3455 printer
.info_2
->changeid
= rev_changeid();
3458 * Because one day someone will ask:
3459 * NT->NT An admin connection to a remote
3460 * printer show changes imeediately in
3461 * the properities dialog
3463 * A non-admin connection will only show the
3464 * changes after viewing the properites page
3465 * 2 times. Seems to be related to a
3466 * race condition in the client between the spooler
3467 * updating the local cache and the Explorer.exe GUI
3468 * actually displaying the properties.
3470 * This is fixed in Win2k. admin/non-admin
3471 * connections both display changes immediately.
3476 result
=update_a_printer_2(printer
.info_2
);
3481 result
=WERR_UNKNOWN_LEVEL
;
3488 /****************************************************************************
3489 Initialize printer devmode & data with previously saved driver init values.
3490 ****************************************************************************/
3492 static BOOL
set_driver_init_2( NT_PRINTER_INFO_LEVEL_2
*info_ptr
)
3496 TDB_DATA kbuf
, dbuf
;
3497 NT_PRINTER_INFO_LEVEL_2 info
;
3503 * Delete any printer data 'values' already set. When called for driver
3504 * replace, there will generally be some, but during an add printer, there
3505 * should not be any (if there are delete them).
3508 delete_all_printer_data( info_ptr
, "" );
3510 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info_ptr
->drivername
);
3513 kbuf
.dsize
= strlen(key
)+1;
3515 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
3518 * When changing to a driver that has no init info in the tdb, remove
3519 * the previous drivers init info and leave the new on blank.
3521 free_nt_devicemode(&info_ptr
->devmode
);
3526 * Get the saved DEVMODE..
3529 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3532 * The saved DEVMODE contains the devicename from the printer used during
3533 * the initialization save. Change it to reflect the new printer.
3536 if ( info
.devmode
) {
3537 ZERO_STRUCT(info
.devmode
->devicename
);
3538 fstrcpy(info
.devmode
->devicename
, info_ptr
->printername
);
3542 * NT/2k does not change out the entire DeviceMode of a printer
3543 * when changing the driver. Only the driverextra, private, &
3544 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3546 * Later examination revealed that Windows NT/2k does reset the
3547 * the printer's device mode, bit **only** when you change a
3548 * property of the device mode such as the page orientation.
3553 /* Bind the saved DEVMODE to the new the printer */
3555 free_nt_devicemode(&info_ptr
->devmode
);
3556 info_ptr
->devmode
= info
.devmode
;
3558 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3559 info_ptr
->printername
, info_ptr
->devmode
?"VALID":"NULL", info_ptr
->drivername
));
3561 /* Add the printer data 'values' to the new printer */
3563 len
+= unpack_values( &info_ptr
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3566 SAFE_FREE(dbuf
.dptr
);
3571 /****************************************************************************
3572 Initialize printer devmode & data with previously saved driver init values.
3573 When a printer is created using AddPrinter, the drivername bound to the
3574 printer is used to lookup previously saved driver initialization info, which
3575 is bound to the new printer.
3576 ****************************************************************************/
3578 BOOL
set_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3580 BOOL result
= False
;
3584 result
= set_driver_init_2(printer
->info_2
);
3588 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3596 /****************************************************************************
3597 Delete driver init data stored for a specified driver
3598 ****************************************************************************/
3600 BOOL
del_driver_init(char *drivername
)
3605 if (!drivername
|| !*drivername
) {
3606 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3610 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, drivername
);
3613 kbuf
.dsize
= strlen(key
)+1;
3615 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername
));
3617 return (tdb_delete(tdb_drivers
, kbuf
) == 0);
3620 /****************************************************************************
3621 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3622 in the tdb. Note: this is different from the driver entry and the printer
3623 entry. There should be a single driver init entry for each driver regardless
3624 of whether it was installed from NT or 2K. Technically, they should be
3625 different, but they work out to the same struct.
3626 ****************************************************************************/
3628 static uint32
update_driver_init_2(NT_PRINTER_INFO_LEVEL_2
*info
)
3632 int buflen
, len
, ret
;
3633 TDB_DATA kbuf
, dbuf
;
3640 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
3642 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
3644 if (buflen
!= len
) {
3647 tb
= (char *)Realloc(buf
, len
);
3649 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3659 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info
->drivername
);
3662 kbuf
.dsize
= strlen(key
)+1;
3666 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
3670 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3674 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3675 info
->sharename
, info
->drivername
));
3680 /****************************************************************************
3681 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3682 ****************************************************************************/
3684 uint32
update_driver_init(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3688 dump_a_printer(printer
, level
);
3692 result
= update_driver_init_2(printer
.info_2
);
3702 /****************************************************************************
3703 Convert the printer data value, a REG_BINARY array, into an initialization
3704 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3705 got to keep the endians happy :).
3706 ****************************************************************************/
3708 static BOOL
convert_driver_init( TALLOC_CTX
*ctx
, NT_DEVICEMODE
*nt_devmode
, uint8
*data
, uint32 data_len
)
3710 BOOL result
= False
;
3714 ZERO_STRUCT(devmode
);
3716 prs_init(&ps
, 0, ctx
, UNMARSHALL
);
3717 ps
.data_p
= (char *)data
;
3718 ps
.buffer_size
= data_len
;
3720 if (spoolss_io_devmode("phantom DEVMODE", &ps
, 0, &devmode
))
3721 result
= convert_devicemode("", &devmode
, &nt_devmode
);
3723 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3728 /****************************************************************************
3729 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3731 1. Use the driver's config DLL to this UNC printername and:
3732 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3733 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3734 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3736 The last step triggers saving the "driver initialization" information for
3737 this printer into the tdb. Later, new printers that use this driver will
3738 have this initialization information bound to them. This simulates the
3739 driver initialization, as if it had run on the Samba server (as it would
3742 The Win32 client side code requirement sucks! But until we can run arbitrary
3743 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3745 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3746 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3747 about it and you will realize why. JRR 010720
3748 ****************************************************************************/
3750 static WERROR
save_driver_init_2(NT_PRINTER_INFO_LEVEL
*printer
, uint8
*data
, uint32 data_len
)
3752 WERROR status
= WERR_OK
;
3753 TALLOC_CTX
*ctx
= NULL
;
3754 NT_DEVICEMODE
*nt_devmode
= NULL
;
3755 NT_DEVICEMODE
*tmp_devmode
= printer
->info_2
->devmode
;
3758 * When the DEVMODE is already set on the printer, don't try to unpack it.
3760 DEBUG(8,("save_driver_init_2: Enter...\n"));
3762 if ( !printer
->info_2
->devmode
&& data_len
) {
3764 * Set devmode on printer info, so entire printer initialization can be
3768 if ((ctx
= talloc_init("save_driver_init_2")) == NULL
)
3771 if ((nt_devmode
= (NT_DEVICEMODE
*)malloc(sizeof(NT_DEVICEMODE
))) == NULL
) {
3772 status
= WERR_NOMEM
;
3776 ZERO_STRUCTP(nt_devmode
);
3779 * The DEVMODE is held in the 'data' component of the param in raw binary.
3780 * Convert it to to a devmode structure
3782 if ( !convert_driver_init( ctx
, nt_devmode
, data
, data_len
)) {
3783 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3784 status
= WERR_INVALID_PARAM
;
3788 printer
->info_2
->devmode
= nt_devmode
;
3792 * Pack up and add (or update) the DEVMODE and any current printer data to
3793 * a 'driver init' element in the tdb
3797 if ( update_driver_init(*printer
, 2) != 0 ) {
3798 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3799 status
= WERR_NOMEM
;
3804 * If driver initialization info was successfully saved, set the current
3805 * printer to match it. This allows initialization of the current printer
3806 * as well as the driver.
3808 status
= mod_a_printer(*printer
, 2);
3809 if (!W_ERROR_IS_OK(status
)) {
3810 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3811 printer
->info_2
->printername
));
3815 talloc_destroy(ctx
);
3816 free_nt_devicemode( &nt_devmode
);
3818 printer
->info_2
->devmode
= tmp_devmode
;
3823 /****************************************************************************
3824 Update the driver init info (DEVMODE and specifics) for a printer
3825 ****************************************************************************/
3827 WERROR
save_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
, uint8
*data
, uint32 data_len
)
3829 WERROR status
= WERR_OK
;
3833 status
= save_driver_init_2( printer
, data
, data_len
);
3836 status
= WERR_UNKNOWN_LEVEL
;
3843 /****************************************************************************
3844 Deep copy a NT_PRINTER_DATA
3845 ****************************************************************************/
3847 static NTSTATUS
copy_printer_data( NT_PRINTER_DATA
*dst
, NT_PRINTER_DATA
*src
)
3849 int i
, j
, num_vals
, new_key_index
;
3850 REGVAL_CTR
*src_key
, *dst_key
;
3853 return NT_STATUS_NO_MEMORY
;
3855 for ( i
=0; i
<src
->num_keys
; i
++ ) {
3857 /* create a new instance of the printerkey in the destination
3858 printer_data object */
3860 new_key_index
= add_new_printer_key( dst
, src
->keys
[i
].name
);
3861 dst_key
= &dst
->keys
[new_key_index
].values
;
3863 src_key
= &src
->keys
[i
].values
;
3864 num_vals
= regval_ctr_numvals( src_key
);
3866 /* dup the printer entire printer key */
3868 for ( j
=0; j
<num_vals
; j
++ ) {
3869 regval_ctr_copyvalue( dst_key
, regval_ctr_specific_value(src_key
, j
) );
3873 return NT_STATUS_OK
;
3876 /****************************************************************************
3877 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
3879 ****************************************************************************/
3881 NT_PRINTER_INFO_LEVEL_2
* dup_printer_2( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL_2
*printer
)
3883 NT_PRINTER_INFO_LEVEL_2
*copy
;
3888 if ( !(copy
= (NT_PRINTER_INFO_LEVEL_2
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2
))) )
3891 memcpy( copy
, printer
, sizeof(NT_PRINTER_INFO_LEVEL_2
) );
3893 /* malloc()'d members copied here */
3895 copy
->devmode
= dup_nt_devicemode( printer
->devmode
);
3897 ZERO_STRUCT( copy
->data
);
3898 copy_printer_data( ©
->data
, &printer
->data
);
3900 /* this is talloc()'d; very ugly that we have a structure that
3901 is half malloc()'d and half talloc()'d but that is the way
3902 that the PRINTER_INFO stuff is written right now. --jerry */
3904 copy
->secdesc_buf
= dup_sec_desc_buf( ctx
, printer
->secdesc_buf
);
3909 /****************************************************************************
3910 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3911 ****************************************************************************/
3913 WERROR
get_a_printer( Printer_entry
*print_hnd
, NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
,
3914 const char *sharename
)
3917 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3921 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename
, (unsigned int)level
));
3925 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
3926 DEBUG(0,("get_a_printer: malloc fail.\n"));
3929 ZERO_STRUCTP(printer
);
3932 * check for cache first. A Printer handle cannot changed
3933 * to another printer object so we only check that the printer
3934 * is actually for a printer and that the printer_info pointer
3938 && (print_hnd
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)
3939 && print_hnd
->printer_info
)
3941 if ( !(printer
->info_2
= dup_printer_2(print_hnd
->ctx
, print_hnd
->printer_info
->info_2
)) ) {
3942 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
3948 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
3950 *pp_printer
= printer
;
3956 /* no cache for this handle; see if we can match one from another handle */
3959 result
= find_printer_in_print_hnd_cache(print_hnd
->ctx
, &printer
->info_2
, sharename
);
3961 /* fail to disk if we don't have it with any open handle */
3963 if ( !print_hnd
|| !W_ERROR_IS_OK(result
) )
3964 result
= get_a_printer_2(&printer
->info_2
, sharename
);
3966 /* we have a new printer now. Save it with this handle */
3968 if ( W_ERROR_IS_OK(result
) ) {
3969 dump_a_printer(*printer
, level
);
3971 /* save a copy in cache */
3972 if ( print_hnd
&& (print_hnd
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)) {
3973 if ( !print_hnd
->printer_info
)
3974 print_hnd
->printer_info
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
));
3976 if ( print_hnd
->printer_info
) {
3977 print_hnd
->printer_info
->info_2
= dup_printer_2(print_hnd
->ctx
, printer
->info_2
);
3979 /* don't fail the lookup just because the cache update failed */
3980 if ( !print_hnd
->printer_info
->info_2
)
3981 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
3984 *pp_printer
= printer
;
3992 result
=WERR_UNKNOWN_LEVEL
;
3996 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename
, (unsigned int)level
, dos_errstr(result
)));
4001 /****************************************************************************
4002 Deletes a NT_PRINTER_INFO_LEVEL struct.
4003 ****************************************************************************/
4005 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
4008 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
4010 DEBUG(104,("freeing a printer at level [%d]\n", level
));
4012 if (printer
== NULL
)
4017 if (printer
->info_2
!= NULL
) {
4018 free_nt_printer_info_level_2(&printer
->info_2
);
4029 SAFE_FREE(*pp_printer
);
4033 /****************************************************************************
4034 ****************************************************************************/
4035 uint32
add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4038 DEBUG(104,("adding a printer at level [%d]\n", level
));
4039 dump_a_printer_driver(driver
, level
);
4043 result
=add_a_printer_driver_3(driver
.info_3
);
4047 result
=add_a_printer_driver_6(driver
.info_6
);
4057 /****************************************************************************
4058 ****************************************************************************/
4060 WERROR
get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL
*driver
, uint32 level
,
4061 fstring drivername
, const char *architecture
, uint32 version
)
4067 /* Sometime we just want any version of the driver */
4069 if ( version
== DRIVER_ANY_VERSION
) {
4070 /* look for Win2k first and then for NT4 */
4071 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4074 if ( !W_ERROR_IS_OK(result
) ) {
4075 result
= get_a_printer_driver_3( &driver
->info_3
,
4076 drivername
, architecture
, 2 );
4079 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4080 architecture
, version
);
4089 if (W_ERROR_IS_OK(result
))
4090 dump_a_printer_driver(*driver
, level
);
4095 /****************************************************************************
4096 ****************************************************************************/
4097 uint32
free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4104 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
4105 if (driver
.info_3
!= NULL
)
4107 info3
=driver
.info_3
;
4108 SAFE_FREE(info3
->dependentfiles
);
4109 ZERO_STRUCTP(info3
);
4119 NT_PRINTER_DRIVER_INFO_LEVEL_6
*info6
;
4120 if (driver
.info_6
!= NULL
) {
4121 info6
=driver
.info_6
;
4122 SAFE_FREE(info6
->dependentfiles
);
4123 SAFE_FREE(info6
->previousnames
);
4124 ZERO_STRUCTP(info6
);
4140 /****************************************************************************
4141 Determine whether or not a particular driver is currently assigned
4143 ****************************************************************************/
4145 BOOL
printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
)
4148 int n_services
= lp_numservices();
4149 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4154 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4156 /* loop through the printers.tdb and check for the drivername */
4158 for (snum
=0; snum
<n_services
; snum
++) {
4159 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
4162 if ( !W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))) )
4165 if ( !StrCaseCmp(info_3
->name
, printer
->info_2
->drivername
) ) {
4166 free_a_printer( &printer
, 2 );
4170 free_a_printer( &printer
, 2 );
4173 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4175 /* report that the driver is not in use by default */
4181 /**********************************************************************
4182 Check to see if a ogiven file is in use by *info
4183 *********************************************************************/
4185 static BOOL
drv_file_in_use( char* file
, NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4192 if ( strequal(file
, info
->driverpath
) )
4195 if ( strequal(file
, info
->datafile
) )
4198 if ( strequal(file
, info
->configfile
) )
4201 if ( strequal(file
, info
->helpfile
) )
4204 /* see of there are any dependent files to examine */
4206 if ( !info
->dependentfiles
)
4209 while ( *info
->dependentfiles
[i
] ) {
4210 if ( strequal(file
, info
->dependentfiles
[i
]) )
4219 /**********************************************************************
4220 Utility function to remove the dependent file pointed to by the
4221 input parameter from the list
4222 *********************************************************************/
4224 static void trim_dependent_file( fstring files
[], int idx
)
4227 /* bump everything down a slot */
4229 while( *files
[idx
+1] ) {
4230 fstrcpy( files
[idx
], files
[idx
+1] );
4239 /**********************************************************************
4240 Check if any of the files used by src are also used by drv
4241 *********************************************************************/
4243 static BOOL
trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*src
,
4244 NT_PRINTER_DRIVER_INFO_LEVEL_3
*drv
)
4246 BOOL in_use
= False
;
4252 /* check each file. Remove it from the src structure if it overlaps */
4254 if ( drv_file_in_use(src
->driverpath
, drv
) ) {
4256 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driverpath
));
4257 fstrcpy( src
->driverpath
, "" );
4260 if ( drv_file_in_use(src
->datafile
, drv
) ) {
4262 DEBUG(10,("Removing datafile [%s] from list\n", src
->datafile
));
4263 fstrcpy( src
->datafile
, "" );
4266 if ( drv_file_in_use(src
->configfile
, drv
) ) {
4268 DEBUG(10,("Removing configfile [%s] from list\n", src
->configfile
));
4269 fstrcpy( src
->configfile
, "" );
4272 if ( drv_file_in_use(src
->helpfile
, drv
) ) {
4274 DEBUG(10,("Removing helpfile [%s] from list\n", src
->helpfile
));
4275 fstrcpy( src
->helpfile
, "" );
4278 /* are there any dependentfiles to examine? */
4280 if ( !src
->dependentfiles
)
4283 while ( *src
->dependentfiles
[i
] ) {
4284 if ( drv_file_in_use(src
->dependentfiles
[i
], drv
) ) {
4286 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependentfiles
[i
]));
4287 trim_dependent_file( src
->dependentfiles
, i
);
4295 /****************************************************************************
4296 Determine whether or not a particular driver files are currently being
4297 used by any other driver.
4299 Return value is True if any files were in use by other drivers
4300 and False otherwise.
4302 Upon return, *info has been modified to only contain the driver files
4303 which are not in use
4304 ****************************************************************************/
4306 BOOL
printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4311 fstring
*list
= NULL
;
4312 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4317 version
= info
->cversion
;
4319 /* loop over all driver versions */
4321 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4323 /* get the list of drivers */
4326 ndrivers
= get_ntdrivers(&list
, info
->environment
, version
);
4328 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4329 ndrivers
, info
->environment
, version
));
4331 /* check each driver for overlap in files */
4333 for (i
=0; i
<ndrivers
; i
++) {
4334 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
4336 ZERO_STRUCT(driver
);
4338 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, list
[i
], info
->environment
, version
)) ) {
4343 /* check if d2 uses any files from d1 */
4344 /* only if this is a different driver than the one being deleted */
4346 if ( !strequal(info
->name
, driver
.info_3
->name
) ) {
4347 if ( trim_overlap_drv_files(info
, driver
.info_3
) ) {
4348 free_a_printer_driver(driver
, 3);
4354 free_a_printer_driver(driver
, 3);
4359 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4361 driver
.info_3
= info
;
4363 if ( DEBUGLEVEL
>= 20 )
4364 dump_a_printer_driver( driver
, 3 );
4369 /****************************************************************************
4370 Actually delete the driver files. Make sure that
4371 printer_driver_files_in_use() return False before calling
4373 ****************************************************************************/
4375 static BOOL
delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
)
4379 connection_struct
*conn
;
4387 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3
->name
, info_3
->cversion
));
4390 * Connect to the print$ share under the same account as the
4391 * user connected to the rpc pipe. Note we must be root to
4395 null_pw
= data_blob( NULL
, 0 );
4396 fstrcpy(res_type
, "A:");
4398 conn
= make_connection_with_chdir( "print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
4402 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4406 /* Save who we are - we are temporarily becoming the connection user. */
4408 if ( !become_user(conn
, conn
->vuid
) ) {
4409 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4413 /* now delete the files; must strip the '\print$' string from
4416 if ( *info_3
->driverpath
) {
4417 if ( (s
= strchr( &info_3
->driverpath
[1], '\\' )) != NULL
) {
4418 DEBUG(10,("deleting driverfile [%s]\n", s
));
4419 unlink_internals(conn
, 0, s
);
4423 if ( *info_3
->configfile
) {
4424 if ( (s
= strchr( &info_3
->configfile
[1], '\\' )) != NULL
) {
4425 DEBUG(10,("deleting configfile [%s]\n", s
));
4426 unlink_internals(conn
, 0, s
);
4430 if ( *info_3
->datafile
) {
4431 if ( (s
= strchr( &info_3
->datafile
[1], '\\' )) != NULL
) {
4432 DEBUG(10,("deleting datafile [%s]\n", s
));
4433 unlink_internals(conn
, 0, s
);
4437 if ( *info_3
->helpfile
) {
4438 if ( (s
= strchr( &info_3
->helpfile
[1], '\\' )) != NULL
) {
4439 DEBUG(10,("deleting helpfile [%s]\n", s
));
4440 unlink_internals(conn
, 0, s
);
4444 /* check if we are done removing files */
4446 if ( info_3
->dependentfiles
) {
4447 while ( *info_3
->dependentfiles
[i
] ) {
4450 /* bypass the "\print$" portion of the path */
4452 if ( (file
= strchr( info_3
->dependentfiles
[i
]+1, '\\' )) != NULL
) {
4453 DEBUG(10,("deleting dependent file [%s]\n", file
));
4454 unlink_internals(conn
, 0, file
);
4466 /****************************************************************************
4467 Remove a printer driver from the TDB. This assumes that the the driver was
4468 previously looked up.
4469 ***************************************************************************/
4471 WERROR
delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
,
4472 uint32 version
, BOOL delete_files
)
4476 TDB_DATA kbuf
, dbuf
;
4477 NT_PRINTER_DRIVER_INFO_LEVEL ctr
;
4479 /* delete the tdb data first */
4481 arch
= get_short_archi(info_3
->environment
);
4482 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
,
4483 arch
, version
, info_3
->name
);
4485 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4486 key
, delete_files
? "TRUE" : "FALSE" ));
4488 ctr
.info_3
= info_3
;
4489 dump_a_printer_driver( ctr
, 3 );
4492 kbuf
.dsize
=strlen(key
)+1;
4494 /* check if the driver actually exists for this environment */
4496 dbuf
= tdb_fetch( tdb_drivers
, kbuf
);
4498 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key
));
4499 return WERR_UNKNOWN_PRINTER_DRIVER
;
4502 SAFE_FREE( dbuf
.dptr
);
4504 /* ok... the driver exists so the delete should return success */
4506 if (tdb_delete(tdb_drivers
, kbuf
) == -1) {
4507 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key
));
4508 return WERR_ACCESS_DENIED
;
4512 * now delete any associated files if delete_files == True
4513 * even if this part failes, we return succes because the
4514 * driver doesn not exist any more
4518 delete_driver_files( info_3
, user
);
4521 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key
));
4526 /****************************************************************************
4527 Store a security desc for a printer.
4528 ****************************************************************************/
4530 WERROR
nt_printing_setsec(const char *printername
, SEC_DESC_BUF
*secdesc_ctr
)
4532 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4533 SEC_DESC_BUF
*old_secdesc_ctr
= NULL
;
4535 TALLOC_CTX
*mem_ctx
= NULL
;
4539 mem_ctx
= talloc_init("nt_printing_setsec");
4540 if (mem_ctx
== NULL
)
4543 /* The old owner and group sids of the security descriptor are not
4544 present when new ACEs are added or removed by changing printer
4545 permissions through NT. If they are NULL in the new security
4546 descriptor then copy them over from the old one. */
4548 if (!secdesc_ctr
->sec
->owner_sid
|| !secdesc_ctr
->sec
->grp_sid
) {
4549 DOM_SID
*owner_sid
, *group_sid
;
4550 SEC_ACL
*dacl
, *sacl
;
4551 SEC_DESC
*psd
= NULL
;
4554 nt_printing_getsec(mem_ctx
, printername
, &old_secdesc_ctr
);
4556 /* Pick out correct owner and group sids */
4558 owner_sid
= secdesc_ctr
->sec
->owner_sid
?
4559 secdesc_ctr
->sec
->owner_sid
:
4560 old_secdesc_ctr
->sec
->owner_sid
;
4562 group_sid
= secdesc_ctr
->sec
->grp_sid
?
4563 secdesc_ctr
->sec
->grp_sid
:
4564 old_secdesc_ctr
->sec
->grp_sid
;
4566 dacl
= secdesc_ctr
->sec
->dacl
?
4567 secdesc_ctr
->sec
->dacl
:
4568 old_secdesc_ctr
->sec
->dacl
;
4570 sacl
= secdesc_ctr
->sec
->sacl
?
4571 secdesc_ctr
->sec
->sacl
:
4572 old_secdesc_ctr
->sec
->sacl
;
4574 /* Make a deep copy of the security descriptor */
4576 psd
= make_sec_desc(mem_ctx
, secdesc_ctr
->sec
->revision
, secdesc_ctr
->sec
->type
,
4577 owner_sid
, group_sid
,
4582 new_secdesc_ctr
= make_sec_desc_buf(mem_ctx
, size
, psd
);
4585 if (!new_secdesc_ctr
) {
4586 new_secdesc_ctr
= secdesc_ctr
;
4589 /* Store the security descriptor in a tdb */
4591 prs_init(&ps
, (uint32
)sec_desc_size(new_secdesc_ctr
->sec
) +
4592 sizeof(SEC_DESC_BUF
), mem_ctx
, MARSHALL
);
4594 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr
,
4596 status
= WERR_BADFUNC
;
4600 slprintf(key
, sizeof(key
)-1, "SECDESC/%s", printername
);
4602 if (tdb_prs_store(tdb_printers
, key
, &ps
)==0) {
4605 DEBUG(1,("Failed to store secdesc for %s\n", printername
));
4606 status
= WERR_BADFUNC
;
4609 /* Free malloc'ed memory */
4615 talloc_destroy(mem_ctx
);
4619 /****************************************************************************
4620 Construct a default security descriptor buffer for a printer.
4621 ****************************************************************************/
4623 static SEC_DESC_BUF
*construct_default_printer_sdb(TALLOC_CTX
*ctx
)
4627 SEC_ACL
*psa
= NULL
;
4628 SEC_DESC_BUF
*sdb
= NULL
;
4629 SEC_DESC
*psd
= NULL
;
4633 /* Create an ACE where Everyone is allowed to print */
4635 init_sec_access(&sa
, PRINTER_ACE_PRINT
);
4636 init_sec_ace(&ace
[0], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4637 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4639 /* Make the security descriptor owned by the Administrators group
4640 on the PDC of the domain. */
4642 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
4643 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4646 /* Backup plan - make printer owned by admins.
4647 This should emulate a lanman printer as security
4648 settings can't be changed. */
4650 sid_copy(&owner_sid
, get_global_sam_sid());
4651 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4654 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
4655 init_sec_ace(&ace
[1], &owner_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4656 sa
, SEC_ACE_FLAG_OBJECT_INHERIT
|
4657 SEC_ACE_FLAG_INHERIT_ONLY
);
4659 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
4660 init_sec_ace(&ace
[2], &owner_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4661 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4663 /* The ACL revision number in rpc_secdesc.h differs from the one
4664 created by NT when setting ACE entries in printer
4665 descriptors. NT4 complains about the property being edited by a
4668 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, 3, ace
)) != NULL
) {
4669 psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
4671 NULL
, psa
, &sd_size
);
4675 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4679 sdb
= make_sec_desc_buf(ctx
, sd_size
, psd
);
4681 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4682 (unsigned int)sd_size
));
4687 /****************************************************************************
4688 Get a security desc for a printer.
4689 ****************************************************************************/
4691 BOOL
nt_printing_getsec(TALLOC_CTX
*ctx
, const char *printername
, SEC_DESC_BUF
**secdesc_ctr
)
4697 if (strlen(printername
) > 2 && (temp
= strchr(printername
+ 2, '\\'))) {
4698 printername
= temp
+ 1;
4701 /* Fetch security descriptor from tdb */
4703 slprintf(key
, sizeof(key
)-1, "SECDESC/%s", printername
);
4705 if (tdb_prs_fetch(tdb_printers
, key
, &ps
, ctx
)!=0 ||
4706 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1)) {
4708 DEBUG(4,("using default secdesc for %s\n", printername
));
4710 if (!(*secdesc_ctr
= construct_default_printer_sdb(ctx
))) {
4714 /* Save default security descriptor for later */
4716 prs_init(&ps
, (uint32
)sec_desc_size((*secdesc_ctr
)->sec
) +
4717 sizeof(SEC_DESC_BUF
), ctx
, MARSHALL
);
4719 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1))
4720 tdb_prs_store(tdb_printers
, key
, &ps
);
4727 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4728 this security descriptor has been created when winbindd was
4729 down. Take ownership of security descriptor. */
4731 if (sid_equal((*secdesc_ctr
)->sec
->owner_sid
, &global_sid_World
)) {
4734 /* Change sd owner to workgroup administrator */
4736 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
4737 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4738 SEC_DESC
*psd
= NULL
;
4743 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4745 psd
= make_sec_desc(ctx
, (*secdesc_ctr
)->sec
->revision
, (*secdesc_ctr
)->sec
->type
,
4747 (*secdesc_ctr
)->sec
->grp_sid
,
4748 (*secdesc_ctr
)->sec
->sacl
,
4749 (*secdesc_ctr
)->sec
->dacl
,
4752 new_secdesc_ctr
= make_sec_desc_buf(ctx
, size
, psd
);
4754 /* Swap with other one */
4756 *secdesc_ctr
= new_secdesc_ctr
;
4760 nt_printing_setsec(printername
, *secdesc_ctr
);
4764 if (DEBUGLEVEL
>= 10) {
4765 SEC_ACL
*the_acl
= (*secdesc_ctr
)->sec
->dacl
;
4768 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4769 printername
, the_acl
->num_aces
));
4771 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4774 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
4776 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str
,
4777 the_acl
->ace
[i
].type
, the_acl
->ace
[i
].flags
,
4778 the_acl
->ace
[i
].info
.mask
));
4788 1: level not implemented
4789 2: file doesn't exist
4790 3: can't allocate memory
4791 4: can't free memory
4792 5: non existant struct
4796 A printer and a printer driver are 2 different things.
4797 NT manages them separatelly, Samba does the same.
4798 Why ? Simply because it's easier and it makes sense !
4800 Now explanation: You have 3 printers behind your samba server,
4801 2 of them are the same make and model (laser A and B). But laser B
4802 has an 3000 sheet feeder and laser A doesn't such an option.
4803 Your third printer is an old dot-matrix model for the accounting :-).
4805 If the /usr/local/samba/lib directory (default dir), you will have
4806 5 files to describe all of this.
4808 3 files for the printers (1 by printer):
4811 NTprinter_accounting
4812 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4813 NTdriver_printer model X
4814 NTdriver_printer model Y
4816 jfm: I should use this comment for the text file to explain
4817 same thing for the forms BTW.
4818 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4822 /* Convert generic access rights to printer object specific access rights.
4823 It turns out that NT4 security descriptors use generic access rights and
4824 NT5 the object specific ones. */
4826 void map_printer_permissions(SEC_DESC
*sd
)
4830 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
4831 se_map_generic(&sd
->dacl
->ace
[i
].info
.mask
,
4832 &printer_generic_mapping
);
4836 /****************************************************************************
4837 Check a user has permissions to perform the given operation. We use the
4838 permission constants defined in include/rpc_spoolss.h to check the various
4839 actions we perform when checking printer access.
4841 PRINTER_ACCESS_ADMINISTER:
4842 print_queue_pause, print_queue_resume, update_printer_sec,
4843 update_printer, spoolss_addprinterex_level_2,
4844 _spoolss_setprinterdata
4849 JOB_ACCESS_ADMINISTER:
4850 print_job_delete, print_job_pause, print_job_resume,
4853 ****************************************************************************/
4854 BOOL
print_access_check(struct current_user
*user
, int snum
, int access_type
)
4856 SEC_DESC_BUF
*secdesc
= NULL
;
4857 uint32 access_granted
;
4861 TALLOC_CTX
*mem_ctx
= NULL
;
4862 extern struct current_user current_user
;
4864 /* If user is NULL then use the current_user structure */
4867 user
= ¤t_user
;
4869 /* Always allow root or printer admins to do anything */
4871 if (user
->uid
== 0 ||
4872 user_in_list(uidtoname(user
->uid
), lp_printer_admin(snum
), user
->groups
, user
->ngroups
)) {
4876 /* Get printer name */
4878 pname
= PRINTERNAME(snum
);
4880 if (!pname
|| !*pname
) {
4885 /* Get printer security descriptor */
4887 if(!(mem_ctx
= talloc_init("print_access_check"))) {
4892 nt_printing_getsec(mem_ctx
, pname
, &secdesc
);
4894 if (access_type
== JOB_ACCESS_ADMINISTER
) {
4895 SEC_DESC_BUF
*parent_secdesc
= secdesc
;
4897 /* Create a child security descriptor to check permissions
4898 against. This is because print jobs are child objects
4899 objects of a printer. */
4901 secdesc
= se_create_child_secdesc(mem_ctx
, parent_secdesc
->sec
, False
);
4903 /* Now this is the bit that really confuses me. The access
4904 type needs to be changed from JOB_ACCESS_ADMINISTER to
4905 PRINTER_ACCESS_ADMINISTER for this to work. Something
4906 to do with the child (job) object becoming like a
4909 access_type
= PRINTER_ACCESS_ADMINISTER
;
4914 map_printer_permissions(secdesc
->sec
);
4916 result
= se_access_check(secdesc
->sec
, user
->nt_user_token
, access_type
,
4917 &access_granted
, &status
);
4919 DEBUG(4, ("access check was %s\n", result
? "SUCCESS" : "FAILURE"));
4921 talloc_destroy(mem_ctx
);
4929 /****************************************************************************
4930 Check the time parameters allow a print operation.
4931 *****************************************************************************/
4933 BOOL
print_time_access_check(int snum
)
4935 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4937 time_t now
= time(NULL
);
4941 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))))
4944 if (printer
->info_2
->starttime
== 0 && printer
->info_2
->untiltime
== 0)
4948 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
4950 if (mins
>= printer
->info_2
->starttime
&& mins
<= printer
->info_2
->untiltime
)
4953 free_a_printer(&printer
, 2);