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 Function to allow filename parsing "the old way".
372 ********************************************************************/
374 static BOOL
driver_unix_convert(char *name
,connection_struct
*conn
,
375 char *saved_last_component
, BOOL
*bad_path
, SMB_STRUCT_STAT
*pst
)
378 unix_clean_name(name
);
379 trim_string(name
,"/","/");
380 return unix_convert(name
, conn
, saved_last_component
, bad_path
, pst
);
383 /*******************************************************************
384 tdb traversal function for counting printers.
385 ********************************************************************/
387 static int traverse_counting_printers(TDB_CONTEXT
*t
, TDB_DATA key
,
388 TDB_DATA data
, void *context
)
390 int *printer_count
= (int*)context
;
392 if (memcmp(PRINTERS_PREFIX
, key
.dptr
, sizeof(PRINTERS_PREFIX
)-1) == 0) {
394 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key
.dptr
, *printer_count
));
400 /*******************************************************************
401 Update the spooler global c_setprinter. This variable is initialized
402 when the parent smbd starts with the number of existing printers. It
403 is monotonically increased by the current number of printers *after*
404 each add or delete printer RPC. Only Microsoft knows why... JRR020119
405 ********************************************************************/
407 uint32
update_c_setprinter(BOOL initialize
)
410 int32 printer_count
= 0;
412 tdb_lock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
, 0);
414 /* Traverse the tdb, counting the printers */
415 tdb_traverse(tdb_printers
, traverse_counting_printers
, (void *)&printer_count
);
417 /* If initializing, set c_setprinter to current printers count
418 * otherwise, bump it by the current printer count
421 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
) + printer_count
;
423 c_setprinter
= printer_count
;
425 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter
));
426 tdb_store_int32(tdb_printers
, GLOBAL_C_SETPRINTER
, c_setprinter
);
428 tdb_unlock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
430 return (uint32
)c_setprinter
;
433 /*******************************************************************
434 Get the spooler global c_setprinter, accounting for initialization.
435 ********************************************************************/
437 uint32
get_c_setprinter(void)
439 int32 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
);
441 if (c_setprinter
== (int32
)-1)
442 c_setprinter
= update_c_setprinter(True
);
444 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter
));
446 return (uint32
)c_setprinter
;
449 /****************************************************************************
450 Get builtin form struct list.
451 ****************************************************************************/
453 int get_builtin_ntforms(nt_forms_struct
**list
)
455 *list
= (nt_forms_struct
*)memdup(&default_forms
[0], sizeof(default_forms
));
456 return sizeof(default_forms
) / sizeof(default_forms
[0]);
459 /****************************************************************************
460 get a builtin form struct
461 ****************************************************************************/
463 BOOL
get_a_builtin_ntform(UNISTR2
*uni_formname
,nt_forms_struct
*form
)
467 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
468 DEBUGADD(6,("Looking for builtin form %s \n", form_name
));
469 count
= sizeof(default_forms
) / sizeof(default_forms
[0]);
470 for (i
=0;i
<count
;i
++) {
471 if (strequal(form_name
,default_forms
[i
].name
)) {
472 DEBUGADD(6,("Found builtin form %s \n", form_name
));
473 memcpy(form
,&default_forms
[i
],sizeof(*form
));
481 /****************************************************************************
482 get a form struct list
483 ****************************************************************************/
484 int get_ntforms(nt_forms_struct
**list
)
486 TDB_DATA kbuf
, newkey
, dbuf
;
488 nt_forms_struct form
;
493 for (kbuf
= tdb_firstkey(tdb_forms
);
495 newkey
= tdb_nextkey(tdb_forms
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
)
497 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) != 0)
500 dbuf
= tdb_fetch(tdb_forms
, kbuf
);
504 fstrcpy(form
.name
, kbuf
.dptr
+strlen(FORMS_PREFIX
));
505 ret
= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dddddddd",
506 &i
, &form
.flag
, &form
.width
, &form
.length
, &form
.left
,
507 &form
.top
, &form
.right
, &form
.bottom
);
508 SAFE_FREE(dbuf
.dptr
);
509 if (ret
!= dbuf
.dsize
)
512 tl
= Realloc(*list
, sizeof(nt_forms_struct
)*(n
+1));
514 DEBUG(0,("get_ntforms: Realloc fail.\n"));
526 /****************************************************************************
527 write a form struct list
528 ****************************************************************************/
529 int write_ntforms(nt_forms_struct
**list
, int number
)
536 for (i
=0;i
<number
;i
++) {
537 /* save index, so list is rebuilt in correct order */
538 len
= tdb_pack(buf
, sizeof(buf
), "dddddddd",
539 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
540 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
542 if (len
> sizeof(buf
)) break;
543 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[i
].name
);
544 kbuf
.dsize
= strlen(key
)+1;
548 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) break;
554 /****************************************************************************
555 add a form struct at the end of the list
556 ****************************************************************************/
557 BOOL
add_a_form(nt_forms_struct
**list
, const FORM
*form
, int *count
)
565 * NT tries to add forms even when
566 * they are already in the base
567 * only update the values if already present
572 unistr2_to_ascii(form_name
, &form
->name
, sizeof(form_name
)-1);
573 for (n
=0; n
<*count
; n
++) {
574 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
575 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name
));
582 if((tl
=Realloc(*list
, (n
+1)*sizeof(nt_forms_struct
))) == NULL
) {
583 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
587 unistr2_to_ascii((*list
)[n
].name
, &form
->name
, sizeof((*list
)[n
].name
)-1);
591 (*list
)[n
].flag
=form
->flags
;
592 (*list
)[n
].width
=form
->size_x
;
593 (*list
)[n
].length
=form
->size_y
;
594 (*list
)[n
].left
=form
->left
;
595 (*list
)[n
].top
=form
->top
;
596 (*list
)[n
].right
=form
->right
;
597 (*list
)[n
].bottom
=form
->bottom
;
602 /****************************************************************************
603 Delete a named form struct.
604 ****************************************************************************/
606 BOOL
delete_a_form(nt_forms_struct
**list
, UNISTR2
*del_name
, int *count
, WERROR
*ret
)
615 unistr2_to_ascii(form_name
, del_name
, sizeof(form_name
)-1);
617 for (n
=0; n
<*count
; n
++) {
618 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
619 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name
));
625 DEBUG(10,("delete_a_form, [%s] not found\n", form_name
));
626 *ret
= WERR_INVALID_PARAM
;
630 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[n
].name
);
631 kbuf
.dsize
= strlen(key
)+1;
633 if (tdb_delete(tdb_forms
, kbuf
) != 0) {
641 /****************************************************************************
642 Update a form struct.
643 ****************************************************************************/
645 void update_a_form(nt_forms_struct
**list
, const FORM
*form
, int count
)
649 unistr2_to_ascii(form_name
, &(form
->name
), sizeof(form_name
)-1);
651 DEBUG(106, ("[%s]\n", form_name
));
652 for (n
=0; n
<count
; n
++) {
653 DEBUGADD(106, ("n [%d]:[%s]\n", n
, (*list
)[n
].name
));
654 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
)))
658 if (n
==count
) return;
660 (*list
)[n
].flag
=form
->flags
;
661 (*list
)[n
].width
=form
->size_x
;
662 (*list
)[n
].length
=form
->size_y
;
663 (*list
)[n
].left
=form
->left
;
664 (*list
)[n
].top
=form
->top
;
665 (*list
)[n
].right
=form
->right
;
666 (*list
)[n
].bottom
=form
->bottom
;
669 /****************************************************************************
670 Get the nt drivers list.
671 Traverse the database and look-up the matching names.
672 ****************************************************************************/
673 int get_ntdrivers(fstring
**list
, const char *architecture
, uint32 version
)
676 const char *short_archi
;
679 TDB_DATA kbuf
, newkey
;
681 short_archi
= get_short_archi(architecture
);
682 slprintf(key
, sizeof(key
)-1, "%s%s/%d/", DRIVERS_PREFIX
, short_archi
, version
);
684 for (kbuf
= tdb_firstkey(tdb_drivers
);
686 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
688 if (strncmp(kbuf
.dptr
, key
, strlen(key
)) != 0)
691 if((fl
= Realloc(*list
, sizeof(fstring
)*(total
+1))) == NULL
) {
692 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
697 fstrcpy((*list
)[total
], kbuf
.dptr
+strlen(key
));
704 /****************************************************************************
705 function to do the mapping between the long architecture name and
707 ****************************************************************************/
708 const char *get_short_archi(const char *long_archi
)
712 DEBUG(107,("Getting architecture dependant directory\n"));
715 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
716 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
718 if (archi_table
[i
].long_archi
==NULL
) {
719 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
723 /* this might be client code - but shouldn't this be an fstrcpy etc? */
726 DEBUGADD(108,("index: [%d]\n", i
));
727 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
728 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
730 return archi_table
[i
].short_archi
;
733 /****************************************************************************
734 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
735 There are two case to be covered here: PE (Portable Executable) and NE (New
736 Executable) files. Both files support the same INFO structure, but PE files
737 store the signature in unicode, and NE files store it as !unicode.
738 returns -1 on error, 1 on version info found, and 0 on no version info found.
739 ****************************************************************************/
741 static int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
747 if ((buf
=malloc(PE_HEADER_SIZE
)) == NULL
) {
748 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
749 fname
, PE_HEADER_SIZE
));
753 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
754 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
755 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
756 fname
, (unsigned long)byte_count
));
757 goto no_version_info
;
760 /* Is this really a DOS header? */
761 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
762 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
763 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
764 goto no_version_info
;
767 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
768 if (SMB_VFS_LSEEK(fsp
, fsp
->fd
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
769 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
771 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
772 goto no_version_info
;
775 if ((byte_count
= vfs_read_data(fsp
, buf
, PE_HEADER_SIZE
)) < PE_HEADER_SIZE
) {
776 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
777 fname
, (unsigned long)byte_count
));
778 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
779 goto no_version_info
;
782 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
783 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
784 unsigned int num_sections
;
785 unsigned int section_table_bytes
;
787 if (SVAL(buf
,PE_HEADER_MACHINE_OFFSET
) != PE_HEADER_MACHINE_I386
) {
788 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
789 fname
, SVAL(buf
,PE_HEADER_MACHINE_OFFSET
)));
790 /* At this point, we assume the file is in error. It still could be somthing
791 * else besides a PE file, but it unlikely at this point.
796 /* get the section table */
797 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
798 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
799 if (section_table_bytes
== 0)
803 if ((buf
=malloc(section_table_bytes
)) == NULL
) {
804 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
805 fname
, section_table_bytes
));
809 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
810 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
811 fname
, (unsigned long)byte_count
));
815 /* Iterate the section table looking for the resource section ".rsrc" */
816 for (i
= 0; i
< num_sections
; i
++) {
817 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
819 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
820 unsigned int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
821 unsigned int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
823 if (section_bytes
== 0)
827 if ((buf
=malloc(section_bytes
)) == NULL
) {
828 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
829 fname
, section_bytes
));
833 /* Seek to the start of the .rsrc section info */
834 if (SMB_VFS_LSEEK(fsp
, fsp
->fd
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
835 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
840 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
841 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
842 fname
, (unsigned long)byte_count
));
846 if (section_bytes
< VS_VERSION_INFO_UNICODE_SIZE
)
849 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
850 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
851 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
852 /* Align to next long address */
853 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
855 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
856 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
857 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
859 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
860 fname
, *major
, *minor
,
861 (*major
>>16)&0xffff, *major
&0xffff,
862 (*minor
>>16)&0xffff, *minor
&0xffff));
871 /* Version info not found, fall back to origin date/time */
872 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
876 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
877 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
878 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
879 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
880 /* At this point, we assume the file is in error. It still could be somthing
881 * else besides a NE file, but it unlikely at this point. */
885 /* Allocate a bit more space to speed up things */
887 if ((buf
=malloc(VS_NE_BUF_SIZE
)) == NULL
) {
888 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
889 fname
, PE_HEADER_SIZE
));
893 /* This is a HACK! I got tired of trying to sort through the messy
894 * 'NE' file format. If anyone wants to clean this up please have at
895 * it, but this works. 'NE' files will eventually fade away. JRR */
896 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
897 /* Cover case that should not occur in a well formed 'NE' .dll file */
898 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
900 for(i
=0; i
<byte_count
; i
++) {
901 /* Fast skip past data that can't possibly match */
902 if (buf
[i
] != 'V') continue;
904 /* Potential match data crosses buf boundry, move it to beginning
905 * of buf, and fill the buf with as much as it will hold. */
906 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
909 memcpy(buf
, &buf
[i
], byte_count
-i
);
910 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
911 (byte_count
-i
))) < 0) {
913 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
918 byte_count
= bc
+ (byte_count
- i
);
919 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
924 /* Check that the full signature string and the magic number that
925 * follows exist (not a perfect solution, but the chances that this
926 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
927 * twice, as it is simpler to read the code. */
928 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
929 /* Compute skip alignment to next long address */
930 int skip
= -(SMB_VFS_LSEEK(fsp
, fsp
->fd
, 0, SEEK_CUR
) - (byte_count
- i
) +
931 sizeof(VS_SIGNATURE
)) & 3;
932 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
934 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
935 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
936 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
937 fname
, *major
, *minor
,
938 (*major
>>16)&0xffff, *major
&0xffff,
939 (*minor
>>16)&0xffff, *minor
&0xffff));
946 /* Version info not found, fall back to origin date/time */
947 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
952 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
953 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
954 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
965 /****************************************************************************
966 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
967 share one or more files. During the MS installation process files are checked
968 to insure that only a newer version of a shared file is installed over an
969 older version. There are several possibilities for this comparison. If there
970 is no previous version, the new one is newer (obviously). If either file is
971 missing the version info structure, compare the creation date (on Unix use
972 the modification date). Otherwise chose the numerically larger version number.
973 ****************************************************************************/
975 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
977 BOOL use_version
= True
;
982 time_t new_create_time
;
986 time_t old_create_time
;
990 files_struct
*fsp
= NULL
;
992 SMB_STRUCT_STAT stat_buf
;
996 ZERO_STRUCT(stat_buf
);
997 new_create_time
= (time_t)0;
998 old_create_time
= (time_t)0;
1000 /* Get file version info (if available) for previous file (if it exists) */
1001 pstrcpy(filepath
, old_file
);
1003 driver_unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1005 fsp
= open_file_shared(conn
, filepath
, &stat_buf
,
1006 SET_OPEN_MODE(DOS_OPEN_RDONLY
),
1007 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1008 FILE_ATTRIBUTE_NORMAL
, 0, &access_mode
, &action
);
1010 /* Old file not found, so by definition new file is in fact newer */
1011 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1016 int ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
1017 if (ret
== -1) goto error_exit
;
1020 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1022 use_version
= False
;
1023 if (SMB_VFS_FSTAT(fsp
, fsp
->fd
, &st
) == -1) goto error_exit
;
1024 old_create_time
= st
.st_mtime
;
1025 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time
));
1028 close_file(fsp
, True
);
1030 /* Get file version info (if available) for new file */
1031 pstrcpy(filepath
, new_file
);
1032 driver_unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1034 fsp
= open_file_shared(conn
, filepath
, &stat_buf
,
1035 SET_OPEN_MODE(DOS_OPEN_RDONLY
),
1036 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1037 FILE_ATTRIBUTE_NORMAL
, 0, &access_mode
, &action
);
1039 /* New file not found, this shouldn't occur if the caller did its job */
1040 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1045 int ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
1046 if (ret
== -1) goto error_exit
;
1049 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1051 use_version
= False
;
1052 if (SMB_VFS_FSTAT(fsp
, fsp
->fd
, &st
) == -1) goto error_exit
;
1053 new_create_time
= st
.st_mtime
;
1054 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time
));
1057 close_file(fsp
, True
);
1059 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
1060 /* Compare versions and choose the larger version number */
1061 if (new_major
> old_major
||
1062 (new_major
== old_major
&& new_minor
> old_minor
)) {
1064 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1068 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1073 /* Compare modification time/dates and choose the newest time/date */
1074 if (new_create_time
> old_create_time
) {
1075 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1079 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1086 close_file(fsp
, True
);
1090 /****************************************************************************
1091 Determine the correct cVersion associated with an architecture and driver
1092 ****************************************************************************/
1093 static uint32
get_correct_cversion(const char *architecture
, fstring driverpath_in
,
1094 struct current_user
*user
, WERROR
*perr
)
1103 files_struct
*fsp
= NULL
;
1106 connection_struct
*conn
;
1110 *perr
= WERR_INVALID_PARAM
;
1112 /* If architecture is Windows 95/98/ME, the version is always 0. */
1113 if (strcmp(architecture
, "WIN40") == 0) {
1114 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1120 * Connect to the print$ share under the same account as the user connected
1121 * to the rpc pipe. Note we must still be root to do this.
1124 /* Null password is ok - we are already an authenticated user... */
1125 null_pw
= data_blob(NULL
, 0);
1126 fstrcpy(res_type
, "A:");
1128 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1132 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1133 *perr
= ntstatus_to_werror(nt_status
);
1137 /* We are temporarily becoming the connection user. */
1138 if (!become_user(conn
, user
->vuid
)) {
1139 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1140 *perr
= WERR_ACCESS_DENIED
;
1144 /* Open the driver file (Portable Executable format) and determine the
1145 * deriver the cversion. */
1146 slprintf(driverpath
, sizeof(driverpath
)-1, "%s/%s", architecture
, driverpath_in
);
1148 driver_unix_convert(driverpath
,conn
,NULL
,&bad_path
,&st
);
1150 fsp
= open_file_shared(conn
, driverpath
, &st
,
1151 SET_OPEN_MODE(DOS_OPEN_RDONLY
),
1152 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1153 FILE_ATTRIBUTE_NORMAL
, 0, &access_mode
, &action
);
1155 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1156 driverpath
, errno
));
1157 *perr
= WERR_ACCESS_DENIED
;
1163 int ret
= get_file_version(fsp
, driverpath
, &major
, &minor
);
1164 if (ret
== -1) goto error_exit
;
1167 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath
));
1172 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1173 * for more details. Version in this case is not just the version of the
1174 * file, but the version in the sense of kernal mode (2) vs. user mode
1175 * (3) drivers. Other bits of the version fields are the version info.
1178 cversion
= major
& 0x0000ffff;
1180 case 2: /* WinNT drivers */
1181 case 3: /* Win2K drivers */
1185 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1186 driverpath
, cversion
));
1190 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1191 driverpath
, major
, minor
));
1194 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1195 driverpath
, cversion
));
1197 close_file(fsp
, True
);
1198 close_cnum(conn
, user
->vuid
);
1207 close_file(fsp
, True
);
1209 close_cnum(conn
, user
->vuid
);
1214 /****************************************************************************
1215 ****************************************************************************/
1216 static WERROR
clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
,
1217 struct current_user
*user
)
1219 const char *architecture
;
1225 /* clean up the driver name.
1226 * we can get .\driver.dll
1227 * or worse c:\windows\system\driver.dll !
1229 /* using an intermediate string to not have overlaping memcpy()'s */
1230 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1231 fstrcpy(new_name
, p
+1);
1232 fstrcpy(driver
->driverpath
, new_name
);
1235 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1236 fstrcpy(new_name
, p
+1);
1237 fstrcpy(driver
->datafile
, new_name
);
1240 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1241 fstrcpy(new_name
, p
+1);
1242 fstrcpy(driver
->configfile
, new_name
);
1245 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1246 fstrcpy(new_name
, p
+1);
1247 fstrcpy(driver
->helpfile
, new_name
);
1250 if (driver
->dependentfiles
) {
1251 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1252 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1253 fstrcpy(new_name
, p
+1);
1254 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1259 architecture
= get_short_archi(driver
->environment
);
1261 /* jfm:7/16/2000 the client always sends the cversion=0.
1262 * The server should check which version the driver is by reading
1263 * the PE header of driver->driverpath.
1265 * For Windows 95/98 the version is 0 (so the value sent is correct)
1266 * For Windows NT (the architecture doesn't matter)
1267 * NT 3.1: cversion=0
1268 * NT 3.5/3.51: cversion=1
1272 if ((driver
->cversion
= get_correct_cversion( architecture
,
1273 driver
->driverpath
, user
, &err
)) == -1)
1279 /****************************************************************************
1280 ****************************************************************************/
1281 static WERROR
clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
, struct current_user
*user
)
1283 const char *architecture
;
1289 /* clean up the driver name.
1290 * we can get .\driver.dll
1291 * or worse c:\windows\system\driver.dll !
1293 /* using an intermediate string to not have overlaping memcpy()'s */
1294 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1295 fstrcpy(new_name
, p
+1);
1296 fstrcpy(driver
->driverpath
, new_name
);
1299 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1300 fstrcpy(new_name
, p
+1);
1301 fstrcpy(driver
->datafile
, new_name
);
1304 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1305 fstrcpy(new_name
, p
+1);
1306 fstrcpy(driver
->configfile
, new_name
);
1309 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1310 fstrcpy(new_name
, p
+1);
1311 fstrcpy(driver
->helpfile
, new_name
);
1314 if (driver
->dependentfiles
) {
1315 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1316 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1317 fstrcpy(new_name
, p
+1);
1318 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1323 architecture
= get_short_archi(driver
->environment
);
1325 /* jfm:7/16/2000 the client always sends the cversion=0.
1326 * The server should check which version the driver is by reading
1327 * the PE header of driver->driverpath.
1329 * For Windows 95/98 the version is 0 (so the value sent is correct)
1330 * For Windows NT (the architecture doesn't matter)
1331 * NT 3.1: cversion=0
1332 * NT 3.5/3.51: cversion=1
1336 if ((driver
->version
= get_correct_cversion(architecture
, driver
->driverpath
, user
, &err
)) == -1)
1342 /****************************************************************************
1343 ****************************************************************************/
1344 WERROR
clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
,
1345 uint32 level
, struct current_user
*user
)
1350 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1351 driver
=driver_abstract
.info_3
;
1352 return clean_up_driver_struct_level_3(driver
, user
);
1356 NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
;
1357 driver
=driver_abstract
.info_6
;
1358 return clean_up_driver_struct_level_6(driver
, user
);
1361 return WERR_INVALID_PARAM
;
1365 /****************************************************************************
1366 This function sucks and should be replaced. JRA.
1367 ****************************************************************************/
1369 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*dst
, NT_PRINTER_DRIVER_INFO_LEVEL_6
*src
)
1371 dst
->cversion
= src
->version
;
1373 fstrcpy( dst
->name
, src
->name
);
1374 fstrcpy( dst
->environment
, src
->environment
);
1375 fstrcpy( dst
->driverpath
, src
->driverpath
);
1376 fstrcpy( dst
->datafile
, src
->datafile
);
1377 fstrcpy( dst
->configfile
, src
->configfile
);
1378 fstrcpy( dst
->helpfile
, src
->helpfile
);
1379 fstrcpy( dst
->monitorname
, src
->monitorname
);
1380 fstrcpy( dst
->defaultdatatype
, src
->defaultdatatype
);
1381 dst
->dependentfiles
= src
->dependentfiles
;
1384 #if 0 /* Debugging function */
1386 static char* ffmt(unsigned char *c
){
1388 static char ffmt_str
[17];
1390 for (i
=0; i
<16; i
++) {
1391 if ((c
[i
] < ' ') || (c
[i
] > '~'))
1402 /****************************************************************************
1403 ****************************************************************************/
1404 BOOL
move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
, uint32 level
,
1405 struct current_user
*user
, WERROR
*perr
)
1407 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1408 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver
;
1409 const char *architecture
;
1414 connection_struct
*conn
;
1424 memset(inbuf
, '\0', sizeof(inbuf
));
1425 memset(outbuf
, '\0', sizeof(outbuf
));
1429 driver
=driver_abstract
.info_3
;
1430 else if (level
==6) {
1431 convert_level_6_to_level3(&converted_driver
, driver_abstract
.info_6
);
1432 driver
= &converted_driver
;
1434 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level
));
1438 architecture
= get_short_archi(driver
->environment
);
1441 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1442 * Note we must be root to do this.
1445 null_pw
= data_blob(NULL
, 0);
1446 fstrcpy(res_type
, "A:");
1448 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1452 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1453 *perr
= ntstatus_to_werror(nt_status
);
1458 * Save who we are - we are temporarily becoming the connection user.
1461 if (!become_user(conn
, conn
->vuid
)) {
1462 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1467 * make the directories version and version\driver_name
1468 * under the architecture directory.
1470 DEBUG(5,("Creating first directory\n"));
1471 slprintf(new_dir
, sizeof(new_dir
)-1, "%s/%d", architecture
, driver
->cversion
);
1472 driver_unix_convert(new_dir
, conn
, NULL
, &bad_path
, &st
);
1473 mkdir_internal(conn
, new_dir
);
1475 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1476 * listed for this driver which has already been moved, skip it (note:
1477 * drivers may list the same file name several times. Then check if the
1478 * file already exists in archi\cversion\, if so, check that the version
1479 * info (or time stamps if version info is unavailable) is newer (or the
1480 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1481 * Otherwise, delete the file.
1483 * If a file is not moved to archi\cversion\ because of an error, all the
1484 * rest of the 'unmoved' driver files are removed from archi\. If one or
1485 * more of the driver's files was already moved to archi\cversion\, it
1486 * potentially leaves the driver in a partially updated state. Version
1487 * trauma will most likely occur if an client attempts to use any printer
1488 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1489 * done is appropriate... later JRR
1492 DEBUG(5,("Moving files now !\n"));
1494 if (driver
->driverpath
&& strlen(driver
->driverpath
)) {
1495 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->driverpath
);
1496 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->driverpath
);
1497 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1499 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1500 status
= rename_internals(conn
, new_name
, old_name
, 0, True
);
1501 if (!NT_STATUS_IS_OK(status
)) {
1502 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1503 new_name
, old_name
));
1504 *perr
= ntstatus_to_werror(status
);
1505 unlink_internals(conn
, 0, new_name
);
1509 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1510 unlink_internals(conn
, 0, new_name
);
1514 if (driver
->datafile
&& strlen(driver
->datafile
)) {
1515 if (!strequal(driver
->datafile
, driver
->driverpath
)) {
1516 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->datafile
);
1517 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->datafile
);
1518 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1520 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1521 status
= rename_internals(conn
, new_name
, old_name
, 0, True
);
1522 if (!NT_STATUS_IS_OK(status
)) {
1523 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1524 new_name
, old_name
));
1525 *perr
= ntstatus_to_werror(status
);
1526 unlink_internals(conn
, 0, new_name
);
1530 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1531 unlink_internals(conn
, 0, new_name
);
1536 if (driver
->configfile
&& strlen(driver
->configfile
)) {
1537 if (!strequal(driver
->configfile
, driver
->driverpath
) &&
1538 !strequal(driver
->configfile
, driver
->datafile
)) {
1539 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->configfile
);
1540 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->configfile
);
1541 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1543 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1544 status
= rename_internals(conn
, new_name
, old_name
, 0, True
);
1545 if (!NT_STATUS_IS_OK(status
)) {
1546 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1547 new_name
, old_name
));
1548 *perr
= ntstatus_to_werror(status
);
1549 unlink_internals(conn
, 0, new_name
);
1553 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1554 unlink_internals(conn
, 0, new_name
);
1559 if (driver
->helpfile
&& strlen(driver
->helpfile
)) {
1560 if (!strequal(driver
->helpfile
, driver
->driverpath
) &&
1561 !strequal(driver
->helpfile
, driver
->datafile
) &&
1562 !strequal(driver
->helpfile
, driver
->configfile
)) {
1563 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->helpfile
);
1564 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->helpfile
);
1565 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1567 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1568 status
= rename_internals(conn
, new_name
, old_name
, 0, True
);
1569 if (!NT_STATUS_IS_OK(status
)) {
1570 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1571 new_name
, old_name
));
1572 *perr
= ntstatus_to_werror(status
);
1573 unlink_internals(conn
, 0, new_name
);
1577 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1578 unlink_internals(conn
, 0, new_name
);
1583 if (driver
->dependentfiles
) {
1584 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1585 if (!strequal(driver
->dependentfiles
[i
], driver
->driverpath
) &&
1586 !strequal(driver
->dependentfiles
[i
], driver
->datafile
) &&
1587 !strequal(driver
->dependentfiles
[i
], driver
->configfile
) &&
1588 !strequal(driver
->dependentfiles
[i
], driver
->helpfile
)) {
1590 for (j
=0; j
< i
; j
++) {
1591 if (strequal(driver
->dependentfiles
[i
], driver
->dependentfiles
[j
])) {
1596 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->dependentfiles
[i
]);
1597 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->dependentfiles
[i
]);
1598 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1600 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1601 status
= rename_internals(conn
, new_name
, old_name
, 0, True
);
1602 if (!NT_STATUS_IS_OK(status
)) {
1603 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1604 new_name
, old_name
));
1605 *perr
= ntstatus_to_werror(status
);
1606 unlink_internals(conn
, 0, new_name
);
1610 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1611 unlink_internals(conn
, 0, new_name
);
1618 close_cnum(conn
, user
->vuid
);
1621 return ver
== -1 ? False
: True
;
1624 /****************************************************************************
1625 ****************************************************************************/
1626 static uint32
add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
)
1629 const char *architecture
;
1635 TDB_DATA kbuf
, dbuf
;
1637 architecture
= get_short_archi(driver
->environment
);
1639 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1640 * \\server is added in the rpc server layer.
1641 * It does make sense to NOT store the server's name in the printer TDB.
1644 slprintf(directory
, sizeof(directory
)-1, "\\print$\\%s\\%d\\", architecture
, driver
->cversion
);
1646 /* .inf files do not always list a file for each of the four standard files.
1647 * Don't prepend a path to a null filename, or client claims:
1648 * "The server on which the printer resides does not have a suitable
1649 * <printer driver name> printer driver installed. Click OK if you
1650 * wish to install the driver on your local machine."
1652 if (strlen(driver
->driverpath
)) {
1653 fstrcpy(temp_name
, driver
->driverpath
);
1654 slprintf(driver
->driverpath
, sizeof(driver
->driverpath
)-1, "%s%s", directory
, temp_name
);
1657 if (strlen(driver
->datafile
)) {
1658 fstrcpy(temp_name
, driver
->datafile
);
1659 slprintf(driver
->datafile
, sizeof(driver
->datafile
)-1, "%s%s", directory
, temp_name
);
1662 if (strlen(driver
->configfile
)) {
1663 fstrcpy(temp_name
, driver
->configfile
);
1664 slprintf(driver
->configfile
, sizeof(driver
->configfile
)-1, "%s%s", directory
, temp_name
);
1667 if (strlen(driver
->helpfile
)) {
1668 fstrcpy(temp_name
, driver
->helpfile
);
1669 slprintf(driver
->helpfile
, sizeof(driver
->helpfile
)-1, "%s%s", directory
, temp_name
);
1672 if (driver
->dependentfiles
) {
1673 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1674 fstrcpy(temp_name
, driver
->dependentfiles
[i
]);
1675 slprintf(driver
->dependentfiles
[i
], sizeof(driver
->dependentfiles
[i
])-1, "%s%s", directory
, temp_name
);
1679 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, driver
->cversion
, driver
->name
);
1681 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key
));
1688 len
+= tdb_pack(buf
+len
, buflen
-len
, "dffffffff",
1691 driver
->environment
,
1696 driver
->monitorname
,
1697 driver
->defaultdatatype
);
1699 if (driver
->dependentfiles
) {
1700 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1701 len
+= tdb_pack(buf
+len
, buflen
-len
, "f",
1702 driver
->dependentfiles
[i
]);
1706 if (len
!= buflen
) {
1709 tb
= (char *)Realloc(buf
, len
);
1711 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1722 kbuf
.dsize
= strlen(key
)+1;
1726 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
1730 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key
));
1736 /****************************************************************************
1737 ****************************************************************************/
1738 static uint32
add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
)
1740 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3
;
1743 info3
.cversion
= driver
->version
;
1744 fstrcpy(info3
.name
,driver
->name
);
1745 fstrcpy(info3
.environment
,driver
->environment
);
1746 fstrcpy(info3
.driverpath
,driver
->driverpath
);
1747 fstrcpy(info3
.datafile
,driver
->datafile
);
1748 fstrcpy(info3
.configfile
,driver
->configfile
);
1749 fstrcpy(info3
.helpfile
,driver
->helpfile
);
1750 fstrcpy(info3
.monitorname
,driver
->monitorname
);
1751 fstrcpy(info3
.defaultdatatype
,driver
->defaultdatatype
);
1752 info3
.dependentfiles
= driver
->dependentfiles
;
1754 return add_a_printer_driver_3(&info3
);
1758 /****************************************************************************
1759 ****************************************************************************/
1760 static WERROR
get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, const char *driver
, const char *arch
)
1762 NT_PRINTER_DRIVER_INFO_LEVEL_3 info
;
1766 fstrcpy(info
.name
, driver
);
1767 fstrcpy(info
.defaultdatatype
, "RAW");
1769 fstrcpy(info
.driverpath
, "");
1770 fstrcpy(info
.datafile
, "");
1771 fstrcpy(info
.configfile
, "");
1772 fstrcpy(info
.helpfile
, "");
1774 if ((info
.dependentfiles
=(fstring
*)malloc(2*sizeof(fstring
))) == NULL
)
1777 memset(info
.dependentfiles
, '\0', 2*sizeof(fstring
));
1778 fstrcpy(info
.dependentfiles
[0], "");
1780 *info_ptr
= memdup(&info
, sizeof(info
));
1785 /****************************************************************************
1786 ****************************************************************************/
1787 static WERROR
get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, fstring drivername
, const char *arch
, uint32 version
)
1789 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver
;
1790 TDB_DATA kbuf
, dbuf
;
1791 const char *architecture
;
1796 ZERO_STRUCT(driver
);
1798 architecture
= get_short_archi(arch
);
1800 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1802 if ( strcmp( architecture
, SPL_ARCH_WIN40
) == 0 )
1805 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX
, architecture
, version
, drivername
));
1807 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, version
, drivername
);
1810 kbuf
.dsize
= strlen(key
)+1;
1812 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
1814 return WERR_UNKNOWN_PRINTER_DRIVER
;
1816 len
+= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dffffffff",
1825 driver
.defaultdatatype
);
1828 while (len
< dbuf
.dsize
) {
1831 tddfs
= (fstring
*)Realloc(driver
.dependentfiles
,
1832 sizeof(fstring
)*(i
+2));
1833 if (tddfs
== NULL
) {
1834 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1837 else driver
.dependentfiles
= tddfs
;
1839 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "f",
1840 &driver
.dependentfiles
[i
]);
1844 if (driver
.dependentfiles
!= NULL
)
1845 fstrcpy(driver
.dependentfiles
[i
], "");
1847 SAFE_FREE(dbuf
.dptr
);
1849 if (len
!= dbuf
.dsize
) {
1850 SAFE_FREE(driver
.dependentfiles
);
1852 return get_a_printer_driver_3_default(info_ptr
, drivername
, arch
);
1855 *info_ptr
= (NT_PRINTER_DRIVER_INFO_LEVEL_3
*)memdup(&driver
, sizeof(driver
));
1860 /****************************************************************************
1861 Debugging function, dump at level 6 the struct in the logs.
1862 ****************************************************************************/
1864 static uint32
dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
1867 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
1870 DEBUG(20,("Dumping printer driver at level [%d]\n", level
));
1876 if (driver
.info_3
== NULL
)
1879 info3
=driver
.info_3
;
1881 DEBUGADD(20,("version:[%d]\n", info3
->cversion
));
1882 DEBUGADD(20,("name:[%s]\n", info3
->name
));
1883 DEBUGADD(20,("environment:[%s]\n", info3
->environment
));
1884 DEBUGADD(20,("driverpath:[%s]\n", info3
->driverpath
));
1885 DEBUGADD(20,("datafile:[%s]\n", info3
->datafile
));
1886 DEBUGADD(20,("configfile:[%s]\n", info3
->configfile
));
1887 DEBUGADD(20,("helpfile:[%s]\n", info3
->helpfile
));
1888 DEBUGADD(20,("monitorname:[%s]\n", info3
->monitorname
));
1889 DEBUGADD(20,("defaultdatatype:[%s]\n", info3
->defaultdatatype
));
1891 for (i
=0; info3
->dependentfiles
&&
1892 *info3
->dependentfiles
[i
]; i
++) {
1893 DEBUGADD(20,("dependentfile:[%s]\n",
1894 info3
->dependentfiles
[i
]));
1901 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level
));
1909 /****************************************************************************
1910 ****************************************************************************/
1911 int pack_devicemode(NT_DEVICEMODE
*nt_devmode
, char *buf
, int buflen
)
1915 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", nt_devmode
);
1920 len
+= tdb_pack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1921 nt_devmode
->devicename
,
1922 nt_devmode
->formname
,
1924 nt_devmode
->specversion
,
1925 nt_devmode
->driverversion
,
1927 nt_devmode
->driverextra
,
1928 nt_devmode
->orientation
,
1929 nt_devmode
->papersize
,
1930 nt_devmode
->paperlength
,
1931 nt_devmode
->paperwidth
,
1934 nt_devmode
->defaultsource
,
1935 nt_devmode
->printquality
,
1938 nt_devmode
->yresolution
,
1939 nt_devmode
->ttoption
,
1940 nt_devmode
->collate
,
1941 nt_devmode
->logpixels
,
1944 nt_devmode
->bitsperpel
,
1945 nt_devmode
->pelswidth
,
1946 nt_devmode
->pelsheight
,
1947 nt_devmode
->displayflags
,
1948 nt_devmode
->displayfrequency
,
1949 nt_devmode
->icmmethod
,
1950 nt_devmode
->icmintent
,
1951 nt_devmode
->mediatype
,
1952 nt_devmode
->dithertype
,
1953 nt_devmode
->reserved1
,
1954 nt_devmode
->reserved2
,
1955 nt_devmode
->panningwidth
,
1956 nt_devmode
->panningheight
,
1957 nt_devmode
->private);
1960 if (nt_devmode
->private) {
1961 len
+= tdb_pack(buf
+len
, buflen
-len
, "B",
1962 nt_devmode
->driverextra
,
1963 nt_devmode
->private);
1966 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode
->formname
));
1971 /****************************************************************************
1972 Pack all values in all printer keys
1973 ***************************************************************************/
1975 static int pack_values(NT_PRINTER_DATA
*data
, char *buf
, int buflen
)
1979 REGISTRY_VALUE
*val
;
1980 REGVAL_CTR
*val_ctr
;
1987 /* loop over all keys */
1989 for ( i
=0; i
<data
->num_keys
; i
++ ) {
1990 val_ctr
= &data
->keys
[i
].values
;
1991 num_values
= regval_ctr_numvals( val_ctr
);
1993 /* loop over all values */
1995 for ( j
=0; j
<num_values
; j
++ ) {
1996 /* pathname should be stored as <key>\<value> */
1998 val
= regval_ctr_specific_value( val_ctr
, j
);
1999 pstrcpy( path
, data
->keys
[i
].name
);
2000 pstrcat( path
, "\\" );
2001 pstrcat( path
, regval_name(val
) );
2003 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2008 regval_data_p(val
) );
2015 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", NULL
);
2021 /****************************************************************************
2022 Delete a printer - this just deletes the printer info file, any open
2023 handles are not affected.
2024 ****************************************************************************/
2026 uint32
del_a_printer(char *sharename
)
2031 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
2034 kbuf
.dsize
=strlen(key
)+1;
2036 tdb_delete(tdb_printers
, kbuf
);
2040 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
2041 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
**, const char* sharename
);
2042 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**);
2043 /****************************************************************************
2044 ****************************************************************************/
2045 static WERROR
update_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
)
2051 TDB_DATA kbuf
, dbuf
;
2054 * in addprinter: no servername and the printer is the name
2055 * in setprinter: servername is \\server
2056 * and printer is \\server\\printer
2058 * Samba manages only local printers.
2059 * we currently don't support things like path=\\other_server\printer
2062 if (info
->servername
[0]!='\0') {
2063 trim_string(info
->printername
, info
->servername
, NULL
);
2064 trim_char(info
->printername
, '\\', '\0');
2065 info
->servername
[0]='\0';
2069 * JFM: one day I'll forget.
2070 * below that's info->portname because that's the SAMBA sharename
2071 * and I made NT 'thinks' it's the portname
2072 * the info->sharename is the thing you can name when you add a printer
2073 * that's the short-name when you create shared printer for 95/98
2074 * So I've made a limitation in SAMBA: you can only have 1 printer model
2075 * behind a SAMBA share.
2083 len
+= tdb_pack(buf
+len
, buflen
-len
, "dddddddddddfffffPfffff",
2086 info
->default_priority
,
2103 info
->printprocessor
,
2107 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
2109 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
2111 if (buflen
!= len
) {
2114 tb
= (char *)Realloc(buf
, len
);
2116 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2126 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, info
->sharename
);
2129 kbuf
.dsize
= strlen(key
)+1;
2133 ret
= (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) == 0? WERR_OK
: WERR_NOMEM
);
2136 if (!W_ERROR_IS_OK(ret
))
2137 DEBUG(8, ("error updating printer to tdb on disk\n"));
2141 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2142 info
->sharename
, info
->drivername
, info
->portname
, len
));
2148 /****************************************************************************
2149 Malloc and return an NT devicemode.
2150 ****************************************************************************/
2152 NT_DEVICEMODE
*construct_nt_devicemode(const fstring default_devicename
)
2155 char adevice
[MAXDEVICENAME
];
2156 NT_DEVICEMODE
*nt_devmode
= (NT_DEVICEMODE
*)malloc(sizeof(NT_DEVICEMODE
));
2158 if (nt_devmode
== NULL
) {
2159 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2163 ZERO_STRUCTP(nt_devmode
);
2165 safe_strcpy(adevice
, default_devicename
, sizeof(adevice
)-1);
2166 fstrcpy(nt_devmode
->devicename
, adevice
);
2168 fstrcpy(nt_devmode
->formname
, "Letter");
2170 nt_devmode
->specversion
= 0x0401;
2171 nt_devmode
->driverversion
= 0x0400;
2172 nt_devmode
->size
= 0x00DC;
2173 nt_devmode
->driverextra
= 0x0000;
2174 nt_devmode
->fields
= FORMNAME
| TTOPTION
| PRINTQUALITY
|
2175 DEFAULTSOURCE
| COPIES
| SCALE
|
2176 PAPERSIZE
| ORIENTATION
;
2177 nt_devmode
->orientation
= 1;
2178 nt_devmode
->papersize
= PAPER_LETTER
;
2179 nt_devmode
->paperlength
= 0;
2180 nt_devmode
->paperwidth
= 0;
2181 nt_devmode
->scale
= 0x64;
2182 nt_devmode
->copies
= 1;
2183 nt_devmode
->defaultsource
= BIN_FORMSOURCE
;
2184 nt_devmode
->printquality
= RES_HIGH
; /* 0x0258 */
2185 nt_devmode
->color
= COLOR_MONOCHROME
;
2186 nt_devmode
->duplex
= DUP_SIMPLEX
;
2187 nt_devmode
->yresolution
= 0;
2188 nt_devmode
->ttoption
= TT_SUBDEV
;
2189 nt_devmode
->collate
= COLLATE_FALSE
;
2190 nt_devmode
->icmmethod
= 0;
2191 nt_devmode
->icmintent
= 0;
2192 nt_devmode
->mediatype
= 0;
2193 nt_devmode
->dithertype
= 0;
2195 /* non utilisés par un driver d'imprimante */
2196 nt_devmode
->logpixels
= 0;
2197 nt_devmode
->bitsperpel
= 0;
2198 nt_devmode
->pelswidth
= 0;
2199 nt_devmode
->pelsheight
= 0;
2200 nt_devmode
->displayflags
= 0;
2201 nt_devmode
->displayfrequency
= 0;
2202 nt_devmode
->reserved1
= 0;
2203 nt_devmode
->reserved2
= 0;
2204 nt_devmode
->panningwidth
= 0;
2205 nt_devmode
->panningheight
= 0;
2207 nt_devmode
->private = NULL
;
2211 /****************************************************************************
2212 Deepcopy an NT devicemode.
2213 ****************************************************************************/
2215 NT_DEVICEMODE
*dup_nt_devicemode(NT_DEVICEMODE
*nt_devicemode
)
2217 NT_DEVICEMODE
*new_nt_devicemode
= NULL
;
2219 if ( !nt_devicemode
)
2222 if ((new_nt_devicemode
= (NT_DEVICEMODE
*)memdup(nt_devicemode
, sizeof(NT_DEVICEMODE
))) == NULL
) {
2223 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2227 new_nt_devicemode
->private = NULL
;
2228 if (nt_devicemode
->private != NULL
) {
2229 if ((new_nt_devicemode
->private = memdup(nt_devicemode
->private, nt_devicemode
->driverextra
)) == NULL
) {
2230 SAFE_FREE(new_nt_devicemode
);
2231 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2236 return new_nt_devicemode
;
2239 /****************************************************************************
2240 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2241 ****************************************************************************/
2243 void free_nt_devicemode(NT_DEVICEMODE
**devmode_ptr
)
2245 NT_DEVICEMODE
*nt_devmode
= *devmode_ptr
;
2247 if(nt_devmode
== NULL
)
2250 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2252 SAFE_FREE(nt_devmode
->private);
2253 SAFE_FREE(*devmode_ptr
);
2256 /****************************************************************************
2257 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2258 ****************************************************************************/
2259 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
)
2261 NT_PRINTER_INFO_LEVEL_2
*info
= *info_ptr
;
2262 NT_PRINTER_DATA
*data
;
2268 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2270 free_nt_devicemode(&info
->devmode
);
2272 /* clean up all registry keys */
2275 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2276 SAFE_FREE( data
->keys
[i
].name
);
2277 regval_ctr_destroy( &data
->keys
[i
].values
);
2279 SAFE_FREE( data
->keys
);
2281 /* finally the top level structure */
2283 SAFE_FREE( *info_ptr
);
2287 /****************************************************************************
2288 ****************************************************************************/
2289 int unpack_devicemode(NT_DEVICEMODE
**nt_devmode
, char *buf
, int buflen
)
2293 NT_DEVICEMODE devmode
;
2295 ZERO_STRUCT(devmode
);
2297 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2299 if (!*nt_devmode
) return len
;
2301 len
+= tdb_unpack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2305 &devmode
.specversion
,
2306 &devmode
.driverversion
,
2308 &devmode
.driverextra
,
2309 &devmode
.orientation
,
2311 &devmode
.paperlength
,
2312 &devmode
.paperwidth
,
2315 &devmode
.defaultsource
,
2316 &devmode
.printquality
,
2319 &devmode
.yresolution
,
2325 &devmode
.bitsperpel
,
2327 &devmode
.pelsheight
,
2328 &devmode
.displayflags
,
2329 &devmode
.displayfrequency
,
2333 &devmode
.dithertype
,
2336 &devmode
.panningwidth
,
2337 &devmode
.panningheight
,
2340 if (devmode
.private) {
2341 /* the len in tdb_unpack is an int value and
2342 * devmode.driverextra is only a short
2344 len
+= tdb_unpack(buf
+len
, buflen
-len
, "B", &extra_len
, &devmode
.private);
2345 devmode
.driverextra
=(uint16
)extra_len
;
2347 /* check to catch an invalid TDB entry so we don't segfault */
2348 if (devmode
.driverextra
== 0) {
2349 devmode
.private = NULL
;
2353 *nt_devmode
= (NT_DEVICEMODE
*)memdup(&devmode
, sizeof(devmode
));
2355 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode
.devicename
, devmode
.formname
));
2356 if (devmode
.private)
2357 DEBUG(8,("with a private section of %d bytes\n", devmode
.driverextra
));
2362 /****************************************************************************
2363 Allocate and initialize a new slot.
2364 ***************************************************************************/
2366 static int add_new_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2371 if ( !data
|| !name
)
2374 /* allocate another slot in the NT_PRINTER_KEY array */
2376 d
= Realloc( data
->keys
, sizeof(NT_PRINTER_KEY
)*(data
->num_keys
+1) );
2380 key_index
= data
->num_keys
;
2382 /* initialze new key */
2385 data
->keys
[key_index
].name
= strdup( name
);
2387 ZERO_STRUCTP( &data
->keys
[key_index
].values
);
2389 regval_ctr_init( &data
->keys
[key_index
].values
);
2391 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name
));
2396 /****************************************************************************
2397 search for a registry key name in the existing printer data
2398 ***************************************************************************/
2400 int lookup_printerkey( NT_PRINTER_DATA
*data
, const char *name
)
2405 if ( !data
|| !name
)
2408 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name
));
2410 /* loop over all existing keys */
2412 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2413 if ( strequal(data
->keys
[i
].name
, name
) ) {
2414 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name
));
2424 /****************************************************************************
2425 ***************************************************************************/
2427 uint32
get_printer_subkeys( NT_PRINTER_DATA
*data
, const char* key
, fstring
**subkeys
)
2431 int num_subkeys
= 0;
2433 fstring
*ptr
, *subkeys_ptr
= NULL
;
2439 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2440 if ( StrnCaseCmp(data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2441 /* match sure it is a subkey and not the key itself */
2443 key_len
= strlen( key
);
2444 if ( strlen(data
->keys
[i
].name
) == key_len
)
2447 /* get subkey path */
2449 p
= data
->keys
[i
].name
+ key_len
;
2452 fstrcpy( subkeyname
, p
);
2453 if ( (p
= strchr( subkeyname
, '\\' )) )
2456 /* don't add a key more than once */
2458 for ( j
=0; j
<num_subkeys
; j
++ ) {
2459 if ( strequal( subkeys_ptr
[j
], subkeyname
) )
2463 if ( j
!= num_subkeys
)
2466 /* found a match, so allocate space and copy the name */
2468 if ( !(ptr
= Realloc( subkeys_ptr
, (num_subkeys
+2)*sizeof(fstring
))) ) {
2469 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2471 SAFE_FREE( subkeys
);
2476 fstrcpy( subkeys_ptr
[num_subkeys
], subkeyname
);
2482 /* tag of the end */
2485 fstrcpy(subkeys_ptr
[num_subkeys
], "" );
2487 *subkeys
= subkeys_ptr
;
2493 static void map_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2496 smb_ucs2_t conv_str
[1024];
2499 regval_ctr_delvalue(ctr
, val_name
);
2500 str_size
= push_ucs2(NULL
, conv_str
, sz
, sizeof(conv_str
),
2501 STR_TERMINATE
| STR_NOALIGN
);
2502 regval_ctr_addvalue(ctr
, val_name
, REG_SZ
,
2503 (char *) conv_str
, str_size
);
2506 static void map_dword_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2509 regval_ctr_delvalue(ctr
, val_name
);
2510 regval_ctr_addvalue(ctr
, val_name
, REG_DWORD
,
2511 (char *) &dword
, sizeof(dword
));
2514 static void map_bool_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2517 uint8 bin_bool
= (b
? 1 : 0);
2518 regval_ctr_delvalue(ctr
, val_name
);
2519 regval_ctr_addvalue(ctr
, val_name
, REG_BINARY
,
2520 (char *) &bin_bool
, sizeof(bin_bool
));
2523 static void map_single_multi_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2524 const char *multi_sz
)
2526 smb_ucs2_t
*conv_strs
= NULL
;
2529 /* a multi-sz has to have a null string terminator, i.e., the last
2530 string must be followed by two nulls */
2531 str_size
= (strlen(multi_sz
) + 2) * sizeof(smb_ucs2_t
);
2532 conv_strs
= calloc(str_size
, 1);
2534 push_ucs2(NULL
, conv_strs
, multi_sz
, str_size
,
2535 STR_TERMINATE
| STR_NOALIGN
);
2537 regval_ctr_delvalue(ctr
, val_name
);
2538 regval_ctr_addvalue(ctr
, val_name
, REG_MULTI_SZ
,
2539 (char *) conv_strs
, str_size
);
2540 safe_free(conv_strs
);
2544 /****************************************************************************
2545 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2547 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2548 * @return BOOL indicating success or failure
2549 ***************************************************************************/
2551 static BOOL
map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2
*info2
)
2553 REGVAL_CTR
*ctr
= NULL
;
2555 char *allocated_string
= NULL
;
2556 const char *ascii_str
;
2559 if ((i
= lookup_printerkey(&info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2560 i
= add_new_printer_key(&info2
->data
, SPOOL_DSSPOOLER_KEY
);
2561 ctr
= &info2
->data
.keys
[i
].values
;
2563 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTERNAME
, info2
->sharename
);
2564 map_sz_into_ctr(ctr
, SPOOL_REG_SHORTSERVERNAME
, global_myname());
2566 get_mydnsfullname(longname
);
2567 map_sz_into_ctr(ctr
, SPOOL_REG_SERVERNAME
, longname
);
2569 asprintf(&allocated_string
, "\\\\%s\\%s", longname
, info2
->sharename
);
2570 map_sz_into_ctr(ctr
, SPOOL_REG_UNCNAME
, allocated_string
);
2571 SAFE_FREE(allocated_string
);
2573 map_dword_into_ctr(ctr
, SPOOL_REG_VERSIONNUMBER
, 4);
2574 map_sz_into_ctr(ctr
, SPOOL_REG_DRIVERNAME
, info2
->drivername
);
2575 map_sz_into_ctr(ctr
, SPOOL_REG_LOCATION
, info2
->location
);
2576 map_sz_into_ctr(ctr
, SPOOL_REG_DESCRIPTION
, info2
->comment
);
2577 map_single_multi_sz_into_ctr(ctr
, SPOOL_REG_PORTNAME
, info2
->portname
);
2578 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSEPARATORFILE
, info2
->sepfile
);
2579 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTSTARTTIME
, info2
->starttime
);
2580 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTENDTIME
, info2
->untiltime
);
2581 map_dword_into_ctr(ctr
, SPOOL_REG_PRIORITY
, info2
->priority
);
2583 map_bool_into_ctr(ctr
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
2584 (info2
->attributes
&
2585 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
2587 switch (info2
->attributes
& 0x3) {
2589 ascii_str
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
2592 ascii_str
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
2595 ascii_str
= SPOOL_REGVAL_PRINTDIRECT
;
2598 ascii_str
= "unknown";
2600 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSPOOLING
, ascii_str
);
2605 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2
*info2
,
2609 REGVAL_CTR
*ctr
=NULL
;
2611 /* find the DsSpooler key */
2612 if ((i
= lookup_printerkey(&info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2613 i
= add_new_printer_key(&info2
->data
, SPOOL_DSSPOOLER_KEY
);
2614 ctr
= &info2
->data
.keys
[i
].values
;
2616 regval_ctr_delvalue(ctr
, "objectGUID");
2617 regval_ctr_addvalue(ctr
, "objectGUID", REG_BINARY
,
2618 (char *) &guid
, sizeof(struct uuid
));
2621 static WERROR
publish_it(NT_PRINTER_INFO_LEVEL
*printer
)
2624 TALLOC_CTX
*ctx
= talloc_init("publish_it");
2625 ADS_MODLIST mods
= ads_init_mods(ctx
);
2626 char *prt_dn
= NULL
, *srv_dn
, *srv_cn_0
;
2627 char *srv_dn_utf8
, **srv_cn_utf8
;
2630 const char *attrs
[] = {"objectGUID", NULL
};
2632 WERROR win_rc
= WERR_OK
;
2635 /* set the DsSpooler info and attributes */
2636 if (!(map_nt_printer_info2_to_dsspooler(printer
->info_2
)))
2638 printer
->info_2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
2639 win_rc
= mod_a_printer(*printer
, 2);
2640 if (!W_ERROR_IS_OK(win_rc
)) {
2641 DEBUG(3, ("err %d saving data\n",
2642 W_ERROR_V(win_rc
)));
2646 /* Build the ads mods */
2647 get_local_printer_publishing_data(ctx
, &mods
,
2648 &printer
->info_2
->data
);
2649 ads_mod_str(ctx
, &mods
, SPOOL_REG_PRINTERNAME
,
2650 printer
->info_2
->sharename
);
2652 /* initial ads structure */
2654 ads
= ads_init(NULL
, NULL
, NULL
);
2656 DEBUG(3, ("ads_init() failed\n"));
2657 return WERR_SERVER_UNAVAILABLE
;
2659 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
2660 SAFE_FREE(ads
->auth
.password
);
2661 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
2664 /* ads_connect() will find the DC for us */
2665 ads_rc
= ads_connect(ads
);
2666 if (!ADS_ERR_OK(ads_rc
)) {
2667 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
2669 return WERR_ACCESS_DENIED
;
2672 /* figure out where to publish */
2673 ads_find_machine_acct(ads
, &res
, global_myname());
2675 /* We use ldap_get_dn here as we need the answer
2676 * in utf8 to call ldap_explode_dn(). JRA. */
2678 srv_dn_utf8
= ldap_get_dn(ads
->ld
, res
);
2681 return WERR_SERVER_UNAVAILABLE
;
2683 ads_msgfree(ads
, res
);
2684 srv_cn_utf8
= ldap_explode_dn(srv_dn_utf8
, 1);
2686 ldap_memfree(srv_dn_utf8
);
2688 return WERR_SERVER_UNAVAILABLE
;
2690 /* Now convert to CH_UNIX. */
2691 if (pull_utf8_allocate(&srv_dn
, srv_dn_utf8
) == (size_t)-1) {
2692 ldap_memfree(srv_dn_utf8
);
2693 ldap_memfree(srv_cn_utf8
);
2695 return WERR_SERVER_UNAVAILABLE
;
2697 if (pull_utf8_allocate(&srv_cn_0
, srv_cn_utf8
[0]) == (size_t)-1) {
2698 ldap_memfree(srv_dn_utf8
);
2699 ldap_memfree(srv_cn_utf8
);
2702 return WERR_SERVER_UNAVAILABLE
;
2705 ldap_memfree(srv_dn_utf8
);
2706 ldap_memfree(srv_cn_utf8
);
2708 asprintf(&prt_dn
, "cn=%s-%s,%s", srv_cn_0
,
2709 printer
->info_2
->sharename
, srv_dn
);
2712 SAFE_FREE(srv_cn_0
);
2715 ads_rc
= ads_add_printer_entry(ads
, prt_dn
, ctx
, &mods
);
2716 if (LDAP_ALREADY_EXISTS
== ads_rc
.err
.rc
)
2717 ads_rc
= ads_mod_printer_entry(ads
, prt_dn
, ctx
,&mods
);
2719 /* retreive the guid and store it locally */
2720 if (ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
2721 ads_pull_guid(ads
, res
, &guid
);
2722 ads_msgfree(ads
, res
);
2723 store_printer_guid(printer
->info_2
, guid
);
2724 win_rc
= mod_a_printer(*printer
, 2);
2733 WERROR
unpublish_it(NT_PRINTER_INFO_LEVEL
*printer
)
2738 char *prt_dn
= NULL
;
2741 printer
->info_2
->attributes
^= PRINTER_ATTRIBUTE_PUBLISHED
;
2742 win_rc
= mod_a_printer(*printer
, 2);
2743 if (!W_ERROR_IS_OK(win_rc
)) {
2744 DEBUG(3, ("err %d saving data\n",
2745 W_ERROR_V(win_rc
)));
2749 ads
= ads_init(NULL
, NULL
, NULL
);
2751 DEBUG(3, ("ads_init() failed\n"));
2752 return WERR_SERVER_UNAVAILABLE
;
2754 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
2755 SAFE_FREE(ads
->auth
.password
);
2756 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
2759 /* ads_connect() will find the DC for us */
2760 ads_rc
= ads_connect(ads
);
2761 if (!ADS_ERR_OK(ads_rc
)) {
2762 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
2764 return WERR_ACCESS_DENIED
;
2767 /* remove the printer from the directory */
2768 ads_rc
= ads_find_printer_on_server(ads
, &res
,
2769 printer
->info_2
->sharename
, global_myname());
2770 if (ADS_ERR_OK(ads_rc
) && ads_count_replies(ads
, res
)) {
2771 prt_dn
= ads_get_dn(ads
, res
);
2772 ads_msgfree(ads
, res
);
2773 ads_rc
= ads_del_dn(ads
, prt_dn
);
2774 ads_memfree(ads
, prt_dn
);
2781 /****************************************************************************
2782 * Publish a printer in the directory
2784 * @param snum describing printer service
2785 * @return WERROR indicating status of publishing
2786 ***************************************************************************/
2788 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
2790 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2793 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
2794 if (!W_ERROR_IS_OK(win_rc
))
2798 case SPOOL_DS_PUBLISH
:
2799 case SPOOL_DS_UPDATE
:
2800 win_rc
= publish_it(printer
);
2802 case SPOOL_DS_UNPUBLISH
:
2803 win_rc
= unpublish_it(printer
);
2806 win_rc
= WERR_NOT_SUPPORTED
;
2810 free_a_printer(&printer
, 2);
2814 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
,
2817 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2819 REGISTRY_VALUE
*guid_val
;
2824 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
2825 if (!W_ERROR_IS_OK(win_rc
))
2828 if (!(printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
))
2831 if ((i
= lookup_printerkey(&printer
->info_2
->data
,
2832 SPOOL_DSSPOOLER_KEY
)) < 0)
2835 if (!(ctr
= &printer
->info_2
->data
.keys
[i
].values
)) {
2839 if (!(guid_val
= regval_ctr_getvalue(ctr
, "objectGUID"))) {
2843 if (regval_size(guid_val
) == sizeof(struct uuid
))
2844 memcpy(guid
, regval_data_p(guid_val
), sizeof(struct uuid
));
2850 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
2854 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
,
2860 /****************************************************************************
2861 ***************************************************************************/
2863 WERROR
delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
)
2865 NT_PRINTER_DATA
*data
;
2867 int removed_keys
= 0;
2871 empty_slot
= data
->num_keys
;
2874 return WERR_INVALID_PARAM
;
2876 /* remove all keys */
2878 if ( !strlen(key
) ) {
2879 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2880 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2881 data
->keys
[i
].name
));
2883 SAFE_FREE( data
->keys
[i
].name
);
2884 regval_ctr_destroy( &data
->keys
[i
].values
);
2887 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2890 SAFE_FREE( data
->keys
);
2891 ZERO_STRUCTP( data
);
2896 /* remove a specific key (and all subkeys) */
2898 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2899 if ( StrnCaseCmp( data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2900 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2901 data
->keys
[i
].name
));
2903 SAFE_FREE( data
->keys
[i
].name
);
2904 regval_ctr_destroy( &data
->keys
[i
].values
);
2906 /* mark the slot as empty */
2908 ZERO_STRUCTP( &data
->keys
[i
] );
2912 /* find the first empty slot */
2914 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2915 if ( !data
->keys
[i
].name
) {
2922 if ( i
== data
->num_keys
)
2923 /* nothing was removed */
2924 return WERR_INVALID_PARAM
;
2926 /* move everything down */
2928 for ( i
=empty_slot
+1; i
<data
->num_keys
; i
++ ) {
2929 if ( data
->keys
[i
].name
) {
2930 memcpy( &data
->keys
[empty_slot
], &data
->keys
[i
], sizeof(NT_PRINTER_KEY
) );
2931 ZERO_STRUCTP( &data
->keys
[i
] );
2939 data
->num_keys
-= removed_keys
;
2941 /* sanity check to see if anything is left */
2943 if ( !data
->num_keys
) {
2944 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2
->printername
));
2946 SAFE_FREE( data
->keys
);
2947 ZERO_STRUCTP( data
);
2953 /****************************************************************************
2954 ***************************************************************************/
2956 WERROR
delete_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
2958 WERROR result
= WERR_OK
;
2961 /* we must have names on non-zero length */
2963 if ( !key
|| !*key
|| !value
|| !*value
)
2964 return WERR_INVALID_NAME
;
2966 /* find the printer key first */
2968 key_index
= lookup_printerkey( &p2
->data
, key
);
2969 if ( key_index
== -1 )
2972 /* make sure the value exists so we can return the correct error code */
2974 if ( !regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
) )
2975 return WERR_BADFILE
;
2977 regval_ctr_delvalue( &p2
->data
.keys
[key_index
].values
, value
);
2979 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2985 /****************************************************************************
2986 ***************************************************************************/
2988 WERROR
add_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
,
2989 uint32 type
, uint8
*data
, int real_len
)
2991 WERROR result
= WERR_OK
;
2994 /* we must have names on non-zero length */
2996 if ( !key
|| !*key
|| !value
|| !*value
)
2997 return WERR_INVALID_NAME
;
2999 /* find the printer key first */
3001 key_index
= lookup_printerkey( &p2
->data
, key
);
3002 if ( key_index
== -1 )
3003 key_index
= add_new_printer_key( &p2
->data
, key
);
3005 if ( key_index
== -1 )
3008 regval_ctr_addvalue( &p2
->data
.keys
[key_index
].values
, value
,
3009 type
, (const char *)data
, real_len
);
3011 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3012 key
, value
, type
, real_len
));
3017 /****************************************************************************
3018 ***************************************************************************/
3020 REGISTRY_VALUE
* get_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3024 if ( (key_index
= lookup_printerkey( &p2
->data
, key
)) == -1 )
3027 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3030 return regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
);
3033 /****************************************************************************
3034 Unpack a list of registry values frem the TDB
3035 ***************************************************************************/
3037 static int unpack_values(NT_PRINTER_DATA
*printer_data
, char *buf
, int buflen
)
3041 pstring string
, valuename
, keyname
;
3045 REGISTRY_VALUE
*regval_p
;
3048 /* add the "PrinterDriverData" key first for performance reasons */
3050 add_new_printer_key( printer_data
, SPOOL_PRINTERDATA_KEY
);
3052 /* loop and unpack the rest of the registry values */
3056 /* check to see if there are any more registry values */
3059 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", ®val_p
);
3063 /* unpack the next regval */
3065 len
+= tdb_unpack(buf
+len
, buflen
-len
, "fdB",
3072 * break of the keyname from the value name.
3073 * Should only be one '\' in the string returned.
3076 str
= strrchr( string
, '\\');
3078 /* Put in "PrinterDriverData" is no key specified */
3081 pstrcpy( keyname
, SPOOL_PRINTERDATA_KEY
);
3082 pstrcpy( valuename
, string
);
3086 pstrcpy( keyname
, string
);
3087 pstrcpy( valuename
, str
+1 );
3090 /* see if we need a new key */
3092 if ( (key_index
=lookup_printerkey( printer_data
, keyname
)) == -1 )
3093 key_index
= add_new_printer_key( printer_data
, keyname
);
3095 if ( key_index
== -1 ) {
3096 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3101 /* add the new value */
3103 regval_ctr_addvalue( &printer_data
->keys
[key_index
].values
, valuename
, type
, (const char *)data_p
, size
);
3105 SAFE_FREE(data_p
); /* 'B' option to tdbpack does a malloc() */
3107 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname
, valuename
, size
));
3113 /****************************************************************************
3114 ***************************************************************************/
3116 static void map_to_os2_driver(fstring drivername
)
3118 static BOOL initialised
=False
;
3119 static fstring last_from
,last_to
;
3120 char *mapfile
= lp_os2_driver_map();
3121 char **lines
= NULL
;
3125 if (!strlen(drivername
))
3132 *last_from
= *last_to
= 0;
3136 if (strequal(drivername
,last_from
)) {
3137 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,last_to
));
3138 fstrcpy(drivername
,last_to
);
3142 lines
= file_lines_load(mapfile
, &numlines
);
3143 if (numlines
== 0) {
3144 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile
));
3148 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
3150 for( i
= 0; i
< numlines
; i
++) {
3151 char *nt_name
= lines
[i
];
3152 char *os2_name
= strchr(nt_name
,'=');
3159 while (isspace(*nt_name
))
3162 if (!*nt_name
|| strchr("#;",*nt_name
))
3166 int l
= strlen(nt_name
);
3167 while (l
&& isspace(nt_name
[l
-1])) {
3173 while (isspace(*os2_name
))
3177 int l
= strlen(os2_name
);
3178 while (l
&& isspace(os2_name
[l
-1])) {
3184 if (strequal(nt_name
,drivername
)) {
3185 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername
,os2_name
));
3186 fstrcpy(last_from
,drivername
);
3187 fstrcpy(last_to
,os2_name
);
3188 fstrcpy(drivername
,os2_name
);
3189 file_lines_free(lines
);
3194 file_lines_free(lines
);
3197 /****************************************************************************
3198 Get a default printer info 2 struct.
3199 ****************************************************************************/
3200 static WERROR
get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, const char *sharename
)
3203 NT_PRINTER_INFO_LEVEL_2 info
;
3207 snum
= lp_servicenumber(sharename
);
3209 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", get_called_name());
3210 slprintf(info
.printername
, sizeof(info
.printername
)-1, "\\\\%s\\%s",
3211 get_called_name(), sharename
);
3212 fstrcpy(info
.sharename
, sharename
);
3213 fstrcpy(info
.portname
, SAMBA_PRINTER_PORT_NAME
);
3215 /* by setting the driver name to an empty string, a local NT admin
3216 can now run the **local** APW to install a local printer driver
3217 for a Samba shared printer in 2.2. Without this, drivers **must** be
3218 installed on the Samba server for NT clients --jerry */
3219 #if 0 /* JERRY --do not uncomment-- */
3220 if (!*info
.drivername
)
3221 fstrcpy(info
.drivername
, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3225 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info
.drivername
));
3227 pstrcpy(info
.comment
, "");
3228 fstrcpy(info
.printprocessor
, "winprint");
3229 fstrcpy(info
.datatype
, "RAW");
3231 info
.attributes
= PRINTER_ATTRIBUTE_SAMBA
;
3233 info
.starttime
= 0; /* Minutes since 12:00am GMT */
3234 info
.untiltime
= 0; /* Minutes since 12:00am GMT */
3236 info
.default_priority
= 1;
3237 info
.setuptime
= (uint32
)time(NULL
);
3240 * I changed this as I think it is better to have a generic
3241 * DEVMODE than to crash Win2k explorer.exe --jerry
3242 * See the HP Deskjet 990c Win2k drivers for an example.
3244 * However the default devmode appears to cause problems
3245 * with the HP CLJ 8500 PCL driver. Hence the addition of
3246 * the "default devmode" parameter --jerry 22/01/2002
3249 if (lp_default_devmode(snum
)) {
3250 if ((info
.devmode
= construct_nt_devicemode(info
.printername
)) == NULL
)
3254 info
.devmode
= NULL
;
3257 /* This will get the current RPC talloc context, but we should be
3258 passing this as a parameter... fixme... JRA ! */
3260 if (!nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
))
3263 *info_ptr
= (NT_PRINTER_INFO_LEVEL_2
*)memdup(&info
, sizeof(info
));
3265 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3273 free_nt_devicemode(&info
.devmode
);
3274 return WERR_ACCESS_DENIED
;
3277 /****************************************************************************
3278 ****************************************************************************/
3279 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, const char *sharename
)
3282 NT_PRINTER_INFO_LEVEL_2 info
;
3284 TDB_DATA kbuf
, dbuf
;
3285 fstring printername
;
3286 char adevice
[MAXDEVICENAME
];
3290 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
3293 kbuf
.dsize
= strlen(key
)+1;
3295 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
3297 return get_a_printer_2_default(info_ptr
, sharename
);
3299 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "dddddddddddfffffPfffff",
3302 &info
.default_priority
,
3319 info
.printprocessor
,
3323 /* Samba has to have shared raw drivers. */
3324 info
.attributes
= PRINTER_ATTRIBUTE_SAMBA
;
3326 /* Restore the stripped strings. */
3327 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", get_called_name());
3328 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", get_called_name(),
3330 fstrcpy(info
.printername
, printername
);
3332 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3335 * Some client drivers freak out if there is a NULL devmode
3336 * (probably the driver is not checking before accessing
3337 * the devmode pointer) --jerry
3339 * See comments in get_a_printer_2_default()
3342 if (lp_default_devmode(lp_servicenumber(sharename
)) && !info
.devmode
) {
3343 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3345 info
.devmode
= construct_nt_devicemode(printername
);
3348 safe_strcpy(adevice
, info
.printername
, sizeof(adevice
)-1);
3350 fstrcpy(info
.devmode
->devicename
, adevice
);
3353 len
+= unpack_values( &info
.data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3355 /* This will get the current RPC talloc context, but we should be
3356 passing this as a parameter... fixme... JRA ! */
3358 nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
);
3360 /* Fix for OS/2 drivers. */
3362 if (get_remote_arch() == RA_OS2
)
3363 map_to_os2_driver(info
.drivername
);
3365 SAFE_FREE(dbuf
.dptr
);
3366 *info_ptr
=memdup(&info
, sizeof(info
));
3368 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3369 sharename
, info
.printername
, info
.drivername
));
3374 /****************************************************************************
3375 Debugging function, dump at level 6 the struct in the logs.
3376 ****************************************************************************/
3377 static uint32
dump_a_printer(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3380 NT_PRINTER_INFO_LEVEL_2
*info2
;
3382 DEBUG(106,("Dumping printer at level [%d]\n", level
));
3387 if (printer
.info_2
== NULL
)
3391 info2
=printer
.info_2
;
3393 DEBUGADD(106,("attributes:[%d]\n", info2
->attributes
));
3394 DEBUGADD(106,("priority:[%d]\n", info2
->priority
));
3395 DEBUGADD(106,("default_priority:[%d]\n", info2
->default_priority
));
3396 DEBUGADD(106,("starttime:[%d]\n", info2
->starttime
));
3397 DEBUGADD(106,("untiltime:[%d]\n", info2
->untiltime
));
3398 DEBUGADD(106,("status:[%d]\n", info2
->status
));
3399 DEBUGADD(106,("cjobs:[%d]\n", info2
->cjobs
));
3400 DEBUGADD(106,("averageppm:[%d]\n", info2
->averageppm
));
3401 DEBUGADD(106,("changeid:[%d]\n", info2
->changeid
));
3402 DEBUGADD(106,("c_setprinter:[%d]\n", info2
->c_setprinter
));
3403 DEBUGADD(106,("setuptime:[%d]\n", info2
->setuptime
));
3405 DEBUGADD(106,("servername:[%s]\n", info2
->servername
));
3406 DEBUGADD(106,("printername:[%s]\n", info2
->printername
));
3407 DEBUGADD(106,("sharename:[%s]\n", info2
->sharename
));
3408 DEBUGADD(106,("portname:[%s]\n", info2
->portname
));
3409 DEBUGADD(106,("drivername:[%s]\n", info2
->drivername
));
3410 DEBUGADD(106,("comment:[%s]\n", info2
->comment
));
3411 DEBUGADD(106,("location:[%s]\n", info2
->location
));
3412 DEBUGADD(106,("sepfile:[%s]\n", info2
->sepfile
));
3413 DEBUGADD(106,("printprocessor:[%s]\n", info2
->printprocessor
));
3414 DEBUGADD(106,("datatype:[%s]\n", info2
->datatype
));
3415 DEBUGADD(106,("parameters:[%s]\n", info2
->parameters
));
3421 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level
));
3429 /****************************************************************************
3430 Update the changeid time.
3431 This is SO NASTY as some drivers need this to change, others need it
3432 static. This value will change every second, and I must hope that this
3433 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3435 ****************************************************************************/
3437 static uint32
rev_changeid(void)
3441 get_process_uptime(&tv
);
3444 /* Return changeid as msec since spooler restart */
3445 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
3448 * This setting seems to work well but is too untested
3449 * to replace the above calculation. Left in for experiementation
3450 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3452 return tv
.tv_sec
* 10 + tv
.tv_usec
/ 100000;
3457 * The function below are the high level ones.
3458 * only those ones must be called from the spoolss code.
3462 /****************************************************************************
3463 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3464 ****************************************************************************/
3466 WERROR
mod_a_printer(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3470 dump_a_printer(printer
, level
);
3473 * invalidate cache for all open handles to this printer.
3474 * cache for a given handle will be updated on the next
3478 invalidate_printer_hnd_cache( printer
.info_2
->sharename
);
3484 * Update the changestamp. Emperical tests show that the
3485 * ChangeID is always updated,but c_setprinter is
3486 * global spooler variable (not per printer).
3489 /* ChangeID **must** be increasing over the lifetime
3490 of client's spoolss service in order for the
3491 client's cache to show updates */
3493 printer
.info_2
->changeid
= rev_changeid();
3496 * Because one day someone will ask:
3497 * NT->NT An admin connection to a remote
3498 * printer show changes imeediately in
3499 * the properities dialog
3501 * A non-admin connection will only show the
3502 * changes after viewing the properites page
3503 * 2 times. Seems to be related to a
3504 * race condition in the client between the spooler
3505 * updating the local cache and the Explorer.exe GUI
3506 * actually displaying the properties.
3508 * This is fixed in Win2k. admin/non-admin
3509 * connections both display changes immediately.
3514 result
=update_a_printer_2(printer
.info_2
);
3519 result
=WERR_UNKNOWN_LEVEL
;
3526 /****************************************************************************
3527 Initialize printer devmode & data with previously saved driver init values.
3528 ****************************************************************************/
3530 static BOOL
set_driver_init_2( NT_PRINTER_INFO_LEVEL_2
*info_ptr
)
3534 TDB_DATA kbuf
, dbuf
;
3535 NT_PRINTER_INFO_LEVEL_2 info
;
3541 * Delete any printer data 'values' already set. When called for driver
3542 * replace, there will generally be some, but during an add printer, there
3543 * should not be any (if there are delete them).
3546 delete_all_printer_data( info_ptr
, "" );
3548 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info_ptr
->drivername
);
3551 kbuf
.dsize
= strlen(key
)+1;
3553 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
3556 * When changing to a driver that has no init info in the tdb, remove
3557 * the previous drivers init info and leave the new on blank.
3559 free_nt_devicemode(&info_ptr
->devmode
);
3564 * Get the saved DEVMODE..
3567 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3570 * The saved DEVMODE contains the devicename from the printer used during
3571 * the initialization save. Change it to reflect the new printer.
3574 if ( info
.devmode
) {
3575 ZERO_STRUCT(info
.devmode
->devicename
);
3576 fstrcpy(info
.devmode
->devicename
, info_ptr
->printername
);
3580 * NT/2k does not change out the entire DeviceMode of a printer
3581 * when changing the driver. Only the driverextra, private, &
3582 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3584 * Later examination revealed that Windows NT/2k does reset the
3585 * the printer's device mode, bit **only** when you change a
3586 * property of the device mode such as the page orientation.
3591 /* Bind the saved DEVMODE to the new the printer */
3593 free_nt_devicemode(&info_ptr
->devmode
);
3594 info_ptr
->devmode
= info
.devmode
;
3596 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3597 info_ptr
->printername
, info_ptr
->devmode
?"VALID":"NULL", info_ptr
->drivername
));
3599 /* Add the printer data 'values' to the new printer */
3601 len
+= unpack_values( &info_ptr
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3604 SAFE_FREE(dbuf
.dptr
);
3609 /****************************************************************************
3610 Initialize printer devmode & data with previously saved driver init values.
3611 When a printer is created using AddPrinter, the drivername bound to the
3612 printer is used to lookup previously saved driver initialization info, which
3613 is bound to the new printer.
3614 ****************************************************************************/
3616 BOOL
set_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3618 BOOL result
= False
;
3622 result
= set_driver_init_2(printer
->info_2
);
3626 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3634 /****************************************************************************
3635 Delete driver init data stored for a specified driver
3636 ****************************************************************************/
3638 BOOL
del_driver_init(char *drivername
)
3643 if (!drivername
|| !*drivername
) {
3644 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3648 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, drivername
);
3651 kbuf
.dsize
= strlen(key
)+1;
3653 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername
));
3655 return (tdb_delete(tdb_drivers
, kbuf
) == 0);
3658 /****************************************************************************
3659 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3660 in the tdb. Note: this is different from the driver entry and the printer
3661 entry. There should be a single driver init entry for each driver regardless
3662 of whether it was installed from NT or 2K. Technically, they should be
3663 different, but they work out to the same struct.
3664 ****************************************************************************/
3666 static uint32
update_driver_init_2(NT_PRINTER_INFO_LEVEL_2
*info
)
3670 int buflen
, len
, ret
;
3671 TDB_DATA kbuf
, dbuf
;
3678 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
3680 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
3682 if (buflen
!= len
) {
3685 tb
= (char *)Realloc(buf
, len
);
3687 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3697 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info
->drivername
);
3700 kbuf
.dsize
= strlen(key
)+1;
3704 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
3708 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3712 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3713 info
->sharename
, info
->drivername
));
3718 /****************************************************************************
3719 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3720 ****************************************************************************/
3722 uint32
update_driver_init(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3726 dump_a_printer(printer
, level
);
3730 result
= update_driver_init_2(printer
.info_2
);
3740 /****************************************************************************
3741 Convert the printer data value, a REG_BINARY array, into an initialization
3742 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3743 got to keep the endians happy :).
3744 ****************************************************************************/
3746 static BOOL
convert_driver_init( TALLOC_CTX
*ctx
, NT_DEVICEMODE
*nt_devmode
, uint8
*data
, uint32 data_len
)
3748 BOOL result
= False
;
3752 ZERO_STRUCT(devmode
);
3754 prs_init(&ps
, 0, ctx
, UNMARSHALL
);
3755 ps
.data_p
= (char *)data
;
3756 ps
.buffer_size
= data_len
;
3758 if (spoolss_io_devmode("phantom DEVMODE", &ps
, 0, &devmode
))
3759 result
= convert_devicemode("", &devmode
, &nt_devmode
);
3761 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3766 /****************************************************************************
3767 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3769 1. Use the driver's config DLL to this UNC printername and:
3770 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3771 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3772 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3774 The last step triggers saving the "driver initialization" information for
3775 this printer into the tdb. Later, new printers that use this driver will
3776 have this initialization information bound to them. This simulates the
3777 driver initialization, as if it had run on the Samba server (as it would
3780 The Win32 client side code requirement sucks! But until we can run arbitrary
3781 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3783 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3784 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3785 about it and you will realize why. JRR 010720
3786 ****************************************************************************/
3788 static WERROR
save_driver_init_2(NT_PRINTER_INFO_LEVEL
*printer
, uint8
*data
, uint32 data_len
)
3790 WERROR status
= WERR_OK
;
3791 TALLOC_CTX
*ctx
= NULL
;
3792 NT_DEVICEMODE
*nt_devmode
= NULL
;
3793 NT_DEVICEMODE
*tmp_devmode
= printer
->info_2
->devmode
;
3796 * When the DEVMODE is already set on the printer, don't try to unpack it.
3798 DEBUG(8,("save_driver_init_2: Enter...\n"));
3800 if ( !printer
->info_2
->devmode
&& data_len
) {
3802 * Set devmode on printer info, so entire printer initialization can be
3806 if ((ctx
= talloc_init("save_driver_init_2")) == NULL
)
3809 if ((nt_devmode
= (NT_DEVICEMODE
*)malloc(sizeof(NT_DEVICEMODE
))) == NULL
) {
3810 status
= WERR_NOMEM
;
3814 ZERO_STRUCTP(nt_devmode
);
3817 * The DEVMODE is held in the 'data' component of the param in raw binary.
3818 * Convert it to to a devmode structure
3820 if ( !convert_driver_init( ctx
, nt_devmode
, data
, data_len
)) {
3821 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3822 status
= WERR_INVALID_PARAM
;
3826 printer
->info_2
->devmode
= nt_devmode
;
3830 * Pack up and add (or update) the DEVMODE and any current printer data to
3831 * a 'driver init' element in the tdb
3835 if ( update_driver_init(*printer
, 2) != 0 ) {
3836 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3837 status
= WERR_NOMEM
;
3842 * If driver initialization info was successfully saved, set the current
3843 * printer to match it. This allows initialization of the current printer
3844 * as well as the driver.
3846 status
= mod_a_printer(*printer
, 2);
3847 if (!W_ERROR_IS_OK(status
)) {
3848 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3849 printer
->info_2
->printername
));
3853 talloc_destroy(ctx
);
3854 free_nt_devicemode( &nt_devmode
);
3856 printer
->info_2
->devmode
= tmp_devmode
;
3861 /****************************************************************************
3862 Update the driver init info (DEVMODE and specifics) for a printer
3863 ****************************************************************************/
3865 WERROR
save_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
, uint8
*data
, uint32 data_len
)
3867 WERROR status
= WERR_OK
;
3871 status
= save_driver_init_2( printer
, data
, data_len
);
3874 status
= WERR_UNKNOWN_LEVEL
;
3881 /****************************************************************************
3882 Deep copy a NT_PRINTER_DATA
3883 ****************************************************************************/
3885 static NTSTATUS
copy_printer_data( NT_PRINTER_DATA
*dst
, NT_PRINTER_DATA
*src
)
3887 int i
, j
, num_vals
, new_key_index
;
3888 REGVAL_CTR
*src_key
, *dst_key
;
3891 return NT_STATUS_NO_MEMORY
;
3893 for ( i
=0; i
<src
->num_keys
; i
++ ) {
3895 /* create a new instance of the printerkey in the destination
3896 printer_data object */
3898 new_key_index
= add_new_printer_key( dst
, src
->keys
[i
].name
);
3899 dst_key
= &dst
->keys
[new_key_index
].values
;
3901 src_key
= &src
->keys
[i
].values
;
3902 num_vals
= regval_ctr_numvals( src_key
);
3904 /* dup the printer entire printer key */
3906 for ( j
=0; j
<num_vals
; j
++ ) {
3907 regval_ctr_copyvalue( dst_key
, regval_ctr_specific_value(src_key
, j
) );
3911 return NT_STATUS_OK
;
3914 /****************************************************************************
3915 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
3917 ****************************************************************************/
3919 NT_PRINTER_INFO_LEVEL_2
* dup_printer_2( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL_2
*printer
)
3921 NT_PRINTER_INFO_LEVEL_2
*copy
;
3926 if ( !(copy
= (NT_PRINTER_INFO_LEVEL_2
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2
))) )
3929 memcpy( copy
, printer
, sizeof(NT_PRINTER_INFO_LEVEL_2
) );
3931 /* malloc()'d members copied here */
3933 copy
->devmode
= dup_nt_devicemode( printer
->devmode
);
3935 ZERO_STRUCT( copy
->data
);
3936 copy_printer_data( ©
->data
, &printer
->data
);
3938 /* this is talloc()'d; very ugly that we have a structure that
3939 is half malloc()'d and half talloc()'d but that is the way
3940 that the PRINTER_INFO stuff is written right now. --jerry */
3942 copy
->secdesc_buf
= dup_sec_desc_buf( ctx
, printer
->secdesc_buf
);
3947 /****************************************************************************
3948 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3950 Previously the code had a memory allocation problem because it always
3951 used the TALLOC_CTX from the Printer_entry*. This context lasts
3952 as a long as the original handle is open. So if the client made a lot
3953 of getprinter[data]() calls, the memory usage would climb. Now we use
3954 a short lived TALLOC_CTX for printer_info_2 objects returned. We
3955 still use the Printer_entry->ctx for maintaining the cache copy though
3956 since that object must live as long as the handle by definition.
3959 ****************************************************************************/
3961 WERROR
get_a_printer( Printer_entry
*print_hnd
, NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
,
3962 const char *sharename
)
3965 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3969 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename
, (unsigned int)level
));
3973 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
3974 DEBUG(0,("get_a_printer: malloc fail.\n"));
3977 ZERO_STRUCTP(printer
);
3980 * check for cache first. A Printer handle cannot changed
3981 * to another printer object so we only check that the printer
3982 * is actually for a printer and that the printer_info pointer
3986 && (print_hnd
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)
3987 && print_hnd
->printer_info
)
3989 /* get_talloc_ctx() works here because we need a short
3990 lived talloc context */
3992 if ( !(printer
->info_2
= dup_printer_2(get_talloc_ctx(), print_hnd
->printer_info
->info_2
)) )
3994 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
4000 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
4002 *pp_printer
= printer
;
4008 /* no cache for this handle; see if we can match one from another handle.
4009 Make sure to use a short lived talloc ctx */
4012 result
= find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer
->info_2
, sharename
);
4014 /* fail to disk if we don't have it with any open handle */
4016 if ( !print_hnd
|| !W_ERROR_IS_OK(result
) )
4017 result
= get_a_printer_2(&printer
->info_2
, sharename
);
4019 /* we have a new printer now. Save it with this handle */
4021 if ( W_ERROR_IS_OK(result
) ) {
4022 dump_a_printer(*printer
, level
);
4024 /* save a copy in cache */
4025 if ( print_hnd
&& (print_hnd
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)) {
4026 if ( !print_hnd
->printer_info
)
4027 print_hnd
->printer_info
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
));
4029 if ( print_hnd
->printer_info
) {
4030 /* make sure to use the handle's talloc ctx here since
4031 the printer_2 object must last until the handle is closed */
4033 print_hnd
->printer_info
->info_2
= dup_printer_2(print_hnd
->ctx
, printer
->info_2
);
4035 /* don't fail the lookup just because the cache update failed */
4036 if ( !print_hnd
->printer_info
->info_2
)
4037 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4040 *pp_printer
= printer
;
4048 result
=WERR_UNKNOWN_LEVEL
;
4052 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename
, (unsigned int)level
, dos_errstr(result
)));
4057 /****************************************************************************
4058 Deletes a NT_PRINTER_INFO_LEVEL struct.
4059 ****************************************************************************/
4061 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
4064 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
4066 DEBUG(104,("freeing a printer at level [%d]\n", level
));
4068 if (printer
== NULL
)
4073 if (printer
->info_2
!= NULL
) {
4074 free_nt_printer_info_level_2(&printer
->info_2
);
4085 SAFE_FREE(*pp_printer
);
4089 /****************************************************************************
4090 ****************************************************************************/
4091 uint32
add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4094 DEBUG(104,("adding a printer at level [%d]\n", level
));
4095 dump_a_printer_driver(driver
, level
);
4099 result
=add_a_printer_driver_3(driver
.info_3
);
4103 result
=add_a_printer_driver_6(driver
.info_6
);
4113 /****************************************************************************
4114 ****************************************************************************/
4116 WERROR
get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL
*driver
, uint32 level
,
4117 fstring drivername
, const char *architecture
, uint32 version
)
4123 /* Sometime we just want any version of the driver */
4125 if ( version
== DRIVER_ANY_VERSION
) {
4126 /* look for Win2k first and then for NT4 */
4127 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4130 if ( !W_ERROR_IS_OK(result
) ) {
4131 result
= get_a_printer_driver_3( &driver
->info_3
,
4132 drivername
, architecture
, 2 );
4135 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4136 architecture
, version
);
4145 if (W_ERROR_IS_OK(result
))
4146 dump_a_printer_driver(*driver
, level
);
4151 /****************************************************************************
4152 ****************************************************************************/
4153 uint32
free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4160 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
4161 if (driver
.info_3
!= NULL
)
4163 info3
=driver
.info_3
;
4164 SAFE_FREE(info3
->dependentfiles
);
4165 ZERO_STRUCTP(info3
);
4175 NT_PRINTER_DRIVER_INFO_LEVEL_6
*info6
;
4176 if (driver
.info_6
!= NULL
) {
4177 info6
=driver
.info_6
;
4178 SAFE_FREE(info6
->dependentfiles
);
4179 SAFE_FREE(info6
->previousnames
);
4180 ZERO_STRUCTP(info6
);
4196 /****************************************************************************
4197 Determine whether or not a particular driver is currently assigned
4199 ****************************************************************************/
4201 BOOL
printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
)
4204 int n_services
= lp_numservices();
4205 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4210 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4212 /* loop through the printers.tdb and check for the drivername */
4214 for (snum
=0; snum
<n_services
; snum
++) {
4215 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
4218 if ( !W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))) )
4221 if ( !StrCaseCmp(info_3
->name
, printer
->info_2
->drivername
) ) {
4222 free_a_printer( &printer
, 2 );
4226 free_a_printer( &printer
, 2 );
4229 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4231 /* report that the driver is not in use by default */
4237 /**********************************************************************
4238 Check to see if a ogiven file is in use by *info
4239 *********************************************************************/
4241 static BOOL
drv_file_in_use( char* file
, NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4248 if ( strequal(file
, info
->driverpath
) )
4251 if ( strequal(file
, info
->datafile
) )
4254 if ( strequal(file
, info
->configfile
) )
4257 if ( strequal(file
, info
->helpfile
) )
4260 /* see of there are any dependent files to examine */
4262 if ( !info
->dependentfiles
)
4265 while ( *info
->dependentfiles
[i
] ) {
4266 if ( strequal(file
, info
->dependentfiles
[i
]) )
4275 /**********************************************************************
4276 Utility function to remove the dependent file pointed to by the
4277 input parameter from the list
4278 *********************************************************************/
4280 static void trim_dependent_file( fstring files
[], int idx
)
4283 /* bump everything down a slot */
4285 while( *files
[idx
+1] ) {
4286 fstrcpy( files
[idx
], files
[idx
+1] );
4295 /**********************************************************************
4296 Check if any of the files used by src are also used by drv
4297 *********************************************************************/
4299 static BOOL
trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*src
,
4300 NT_PRINTER_DRIVER_INFO_LEVEL_3
*drv
)
4302 BOOL in_use
= False
;
4308 /* check each file. Remove it from the src structure if it overlaps */
4310 if ( drv_file_in_use(src
->driverpath
, drv
) ) {
4312 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driverpath
));
4313 fstrcpy( src
->driverpath
, "" );
4316 if ( drv_file_in_use(src
->datafile
, drv
) ) {
4318 DEBUG(10,("Removing datafile [%s] from list\n", src
->datafile
));
4319 fstrcpy( src
->datafile
, "" );
4322 if ( drv_file_in_use(src
->configfile
, drv
) ) {
4324 DEBUG(10,("Removing configfile [%s] from list\n", src
->configfile
));
4325 fstrcpy( src
->configfile
, "" );
4328 if ( drv_file_in_use(src
->helpfile
, drv
) ) {
4330 DEBUG(10,("Removing helpfile [%s] from list\n", src
->helpfile
));
4331 fstrcpy( src
->helpfile
, "" );
4334 /* are there any dependentfiles to examine? */
4336 if ( !src
->dependentfiles
)
4339 while ( *src
->dependentfiles
[i
] ) {
4340 if ( drv_file_in_use(src
->dependentfiles
[i
], drv
) ) {
4342 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependentfiles
[i
]));
4343 trim_dependent_file( src
->dependentfiles
, i
);
4351 /****************************************************************************
4352 Determine whether or not a particular driver files are currently being
4353 used by any other driver.
4355 Return value is True if any files were in use by other drivers
4356 and False otherwise.
4358 Upon return, *info has been modified to only contain the driver files
4359 which are not in use
4360 ****************************************************************************/
4362 BOOL
printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4367 fstring
*list
= NULL
;
4368 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4373 version
= info
->cversion
;
4375 /* loop over all driver versions */
4377 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4379 /* get the list of drivers */
4382 ndrivers
= get_ntdrivers(&list
, info
->environment
, version
);
4384 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4385 ndrivers
, info
->environment
, version
));
4387 /* check each driver for overlap in files */
4389 for (i
=0; i
<ndrivers
; i
++) {
4390 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
4392 ZERO_STRUCT(driver
);
4394 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, list
[i
], info
->environment
, version
)) ) {
4399 /* check if d2 uses any files from d1 */
4400 /* only if this is a different driver than the one being deleted */
4402 if ( !strequal(info
->name
, driver
.info_3
->name
) ) {
4403 if ( trim_overlap_drv_files(info
, driver
.info_3
) ) {
4404 free_a_printer_driver(driver
, 3);
4410 free_a_printer_driver(driver
, 3);
4415 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4417 driver
.info_3
= info
;
4419 if ( DEBUGLEVEL
>= 20 )
4420 dump_a_printer_driver( driver
, 3 );
4425 /****************************************************************************
4426 Actually delete the driver files. Make sure that
4427 printer_driver_files_in_use() return False before calling
4429 ****************************************************************************/
4431 static BOOL
delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
)
4435 connection_struct
*conn
;
4445 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3
->name
, info_3
->cversion
));
4448 * Connect to the print$ share under the same account as the
4449 * user connected to the rpc pipe. Note we must be root to
4453 null_pw
= data_blob( NULL
, 0 );
4454 fstrcpy(res_type
, "A:");
4456 conn
= make_connection_with_chdir( "print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
4460 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4464 /* Save who we are - we are temporarily becoming the connection user. */
4466 if ( !become_user(conn
, conn
->vuid
) ) {
4467 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4471 /* now delete the files; must strip the '\print$' string from
4474 if ( *info_3
->driverpath
) {
4475 if ( (s
= strchr( &info_3
->driverpath
[1], '\\' )) != NULL
) {
4476 driver_unix_convert(s
, conn
, NULL
, &bad_path
, &st
);
4477 DEBUG(10,("deleting driverfile [%s]\n", s
));
4478 unlink_internals(conn
, 0, s
);
4482 if ( *info_3
->configfile
) {
4483 if ( (s
= strchr( &info_3
->configfile
[1], '\\' )) != NULL
) {
4484 driver_unix_convert(s
, conn
, NULL
, &bad_path
, &st
);
4485 DEBUG(10,("deleting configfile [%s]\n", s
));
4486 unlink_internals(conn
, 0, s
);
4490 if ( *info_3
->datafile
) {
4491 if ( (s
= strchr( &info_3
->datafile
[1], '\\' )) != NULL
) {
4492 driver_unix_convert(s
, conn
, NULL
, &bad_path
, &st
);
4493 DEBUG(10,("deleting datafile [%s]\n", s
));
4494 unlink_internals(conn
, 0, s
);
4498 if ( *info_3
->helpfile
) {
4499 if ( (s
= strchr( &info_3
->helpfile
[1], '\\' )) != NULL
) {
4500 driver_unix_convert(s
, conn
, NULL
, &bad_path
, &st
);
4501 DEBUG(10,("deleting helpfile [%s]\n", s
));
4502 unlink_internals(conn
, 0, s
);
4506 /* check if we are done removing files */
4508 if ( info_3
->dependentfiles
) {
4509 while ( *info_3
->dependentfiles
[i
] ) {
4512 /* bypass the "\print$" portion of the path */
4514 if ( (file
= strchr( info_3
->dependentfiles
[i
]+1, '\\' )) != NULL
) {
4515 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4516 DEBUG(10,("deleting dependent file [%s]\n", file
));
4517 unlink_internals(conn
, 0, file
);
4529 /****************************************************************************
4530 Remove a printer driver from the TDB. This assumes that the the driver was
4531 previously looked up.
4532 ***************************************************************************/
4534 WERROR
delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
,
4535 uint32 version
, BOOL delete_files
)
4539 TDB_DATA kbuf
, dbuf
;
4540 NT_PRINTER_DRIVER_INFO_LEVEL ctr
;
4542 /* delete the tdb data first */
4544 arch
= get_short_archi(info_3
->environment
);
4545 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
,
4546 arch
, version
, info_3
->name
);
4548 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4549 key
, delete_files
? "TRUE" : "FALSE" ));
4551 ctr
.info_3
= info_3
;
4552 dump_a_printer_driver( ctr
, 3 );
4555 kbuf
.dsize
=strlen(key
)+1;
4557 /* check if the driver actually exists for this environment */
4559 dbuf
= tdb_fetch( tdb_drivers
, kbuf
);
4561 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key
));
4562 return WERR_UNKNOWN_PRINTER_DRIVER
;
4565 SAFE_FREE( dbuf
.dptr
);
4567 /* ok... the driver exists so the delete should return success */
4569 if (tdb_delete(tdb_drivers
, kbuf
) == -1) {
4570 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key
));
4571 return WERR_ACCESS_DENIED
;
4575 * now delete any associated files if delete_files == True
4576 * even if this part failes, we return succes because the
4577 * driver doesn not exist any more
4581 delete_driver_files( info_3
, user
);
4584 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key
));
4589 /****************************************************************************
4590 Store a security desc for a printer.
4591 ****************************************************************************/
4593 WERROR
nt_printing_setsec(const char *printername
, SEC_DESC_BUF
*secdesc_ctr
)
4595 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4596 SEC_DESC_BUF
*old_secdesc_ctr
= NULL
;
4598 TALLOC_CTX
*mem_ctx
= NULL
;
4602 mem_ctx
= talloc_init("nt_printing_setsec");
4603 if (mem_ctx
== NULL
)
4606 /* The old owner and group sids of the security descriptor are not
4607 present when new ACEs are added or removed by changing printer
4608 permissions through NT. If they are NULL in the new security
4609 descriptor then copy them over from the old one. */
4611 if (!secdesc_ctr
->sec
->owner_sid
|| !secdesc_ctr
->sec
->grp_sid
) {
4612 DOM_SID
*owner_sid
, *group_sid
;
4613 SEC_ACL
*dacl
, *sacl
;
4614 SEC_DESC
*psd
= NULL
;
4617 nt_printing_getsec(mem_ctx
, printername
, &old_secdesc_ctr
);
4619 /* Pick out correct owner and group sids */
4621 owner_sid
= secdesc_ctr
->sec
->owner_sid
?
4622 secdesc_ctr
->sec
->owner_sid
:
4623 old_secdesc_ctr
->sec
->owner_sid
;
4625 group_sid
= secdesc_ctr
->sec
->grp_sid
?
4626 secdesc_ctr
->sec
->grp_sid
:
4627 old_secdesc_ctr
->sec
->grp_sid
;
4629 dacl
= secdesc_ctr
->sec
->dacl
?
4630 secdesc_ctr
->sec
->dacl
:
4631 old_secdesc_ctr
->sec
->dacl
;
4633 sacl
= secdesc_ctr
->sec
->sacl
?
4634 secdesc_ctr
->sec
->sacl
:
4635 old_secdesc_ctr
->sec
->sacl
;
4637 /* Make a deep copy of the security descriptor */
4639 psd
= make_sec_desc(mem_ctx
, secdesc_ctr
->sec
->revision
, secdesc_ctr
->sec
->type
,
4640 owner_sid
, group_sid
,
4645 new_secdesc_ctr
= make_sec_desc_buf(mem_ctx
, size
, psd
);
4648 if (!new_secdesc_ctr
) {
4649 new_secdesc_ctr
= secdesc_ctr
;
4652 /* Store the security descriptor in a tdb */
4654 prs_init(&ps
, (uint32
)sec_desc_size(new_secdesc_ctr
->sec
) +
4655 sizeof(SEC_DESC_BUF
), mem_ctx
, MARSHALL
);
4657 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr
,
4659 status
= WERR_BADFUNC
;
4663 slprintf(key
, sizeof(key
)-1, "SECDESC/%s", printername
);
4665 if (tdb_prs_store(tdb_printers
, key
, &ps
)==0) {
4668 DEBUG(1,("Failed to store secdesc for %s\n", printername
));
4669 status
= WERR_BADFUNC
;
4672 /* Free malloc'ed memory */
4678 talloc_destroy(mem_ctx
);
4682 /****************************************************************************
4683 Construct a default security descriptor buffer for a printer.
4684 ****************************************************************************/
4686 static SEC_DESC_BUF
*construct_default_printer_sdb(TALLOC_CTX
*ctx
)
4690 SEC_ACL
*psa
= NULL
;
4691 SEC_DESC_BUF
*sdb
= NULL
;
4692 SEC_DESC
*psd
= NULL
;
4696 /* Create an ACE where Everyone is allowed to print */
4698 init_sec_access(&sa
, PRINTER_ACE_PRINT
);
4699 init_sec_ace(&ace
[0], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4700 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4702 /* Make the security descriptor owned by the Administrators group
4703 on the PDC of the domain. */
4705 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
4706 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4709 /* Backup plan - make printer owned by admins.
4710 This should emulate a lanman printer as security
4711 settings can't be changed. */
4713 sid_copy(&owner_sid
, get_global_sam_sid());
4714 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4717 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
4718 init_sec_ace(&ace
[1], &owner_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4719 sa
, SEC_ACE_FLAG_OBJECT_INHERIT
|
4720 SEC_ACE_FLAG_INHERIT_ONLY
);
4722 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
4723 init_sec_ace(&ace
[2], &owner_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4724 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4726 /* The ACL revision number in rpc_secdesc.h differs from the one
4727 created by NT when setting ACE entries in printer
4728 descriptors. NT4 complains about the property being edited by a
4731 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, 3, ace
)) != NULL
) {
4732 psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
4734 NULL
, psa
, &sd_size
);
4738 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4742 sdb
= make_sec_desc_buf(ctx
, sd_size
, psd
);
4744 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4745 (unsigned int)sd_size
));
4750 /****************************************************************************
4751 Get a security desc for a printer.
4752 ****************************************************************************/
4754 BOOL
nt_printing_getsec(TALLOC_CTX
*ctx
, const char *printername
, SEC_DESC_BUF
**secdesc_ctr
)
4760 if (strlen(printername
) > 2 && (temp
= strchr(printername
+ 2, '\\'))) {
4761 printername
= temp
+ 1;
4764 /* Fetch security descriptor from tdb */
4766 slprintf(key
, sizeof(key
)-1, "SECDESC/%s", printername
);
4768 if (tdb_prs_fetch(tdb_printers
, key
, &ps
, ctx
)!=0 ||
4769 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1)) {
4771 DEBUG(4,("using default secdesc for %s\n", printername
));
4773 if (!(*secdesc_ctr
= construct_default_printer_sdb(ctx
))) {
4777 /* Save default security descriptor for later */
4779 prs_init(&ps
, (uint32
)sec_desc_size((*secdesc_ctr
)->sec
) +
4780 sizeof(SEC_DESC_BUF
), ctx
, MARSHALL
);
4782 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1))
4783 tdb_prs_store(tdb_printers
, key
, &ps
);
4790 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4791 this security descriptor has been created when winbindd was
4792 down. Take ownership of security descriptor. */
4794 if (sid_equal((*secdesc_ctr
)->sec
->owner_sid
, &global_sid_World
)) {
4797 /* Change sd owner to workgroup administrator */
4799 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
4800 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4801 SEC_DESC
*psd
= NULL
;
4806 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4808 psd
= make_sec_desc(ctx
, (*secdesc_ctr
)->sec
->revision
, (*secdesc_ctr
)->sec
->type
,
4810 (*secdesc_ctr
)->sec
->grp_sid
,
4811 (*secdesc_ctr
)->sec
->sacl
,
4812 (*secdesc_ctr
)->sec
->dacl
,
4815 new_secdesc_ctr
= make_sec_desc_buf(ctx
, size
, psd
);
4817 /* Swap with other one */
4819 *secdesc_ctr
= new_secdesc_ctr
;
4823 nt_printing_setsec(printername
, *secdesc_ctr
);
4827 if (DEBUGLEVEL
>= 10) {
4828 SEC_ACL
*the_acl
= (*secdesc_ctr
)->sec
->dacl
;
4831 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4832 printername
, the_acl
->num_aces
));
4834 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4837 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
4839 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str
,
4840 the_acl
->ace
[i
].type
, the_acl
->ace
[i
].flags
,
4841 the_acl
->ace
[i
].info
.mask
));
4851 1: level not implemented
4852 2: file doesn't exist
4853 3: can't allocate memory
4854 4: can't free memory
4855 5: non existant struct
4859 A printer and a printer driver are 2 different things.
4860 NT manages them separatelly, Samba does the same.
4861 Why ? Simply because it's easier and it makes sense !
4863 Now explanation: You have 3 printers behind your samba server,
4864 2 of them are the same make and model (laser A and B). But laser B
4865 has an 3000 sheet feeder and laser A doesn't such an option.
4866 Your third printer is an old dot-matrix model for the accounting :-).
4868 If the /usr/local/samba/lib directory (default dir), you will have
4869 5 files to describe all of this.
4871 3 files for the printers (1 by printer):
4874 NTprinter_accounting
4875 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4876 NTdriver_printer model X
4877 NTdriver_printer model Y
4879 jfm: I should use this comment for the text file to explain
4880 same thing for the forms BTW.
4881 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4885 /* Convert generic access rights to printer object specific access rights.
4886 It turns out that NT4 security descriptors use generic access rights and
4887 NT5 the object specific ones. */
4889 void map_printer_permissions(SEC_DESC
*sd
)
4893 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
4894 se_map_generic(&sd
->dacl
->ace
[i
].info
.mask
,
4895 &printer_generic_mapping
);
4899 /****************************************************************************
4900 Check a user has permissions to perform the given operation. We use the
4901 permission constants defined in include/rpc_spoolss.h to check the various
4902 actions we perform when checking printer access.
4904 PRINTER_ACCESS_ADMINISTER:
4905 print_queue_pause, print_queue_resume, update_printer_sec,
4906 update_printer, spoolss_addprinterex_level_2,
4907 _spoolss_setprinterdata
4912 JOB_ACCESS_ADMINISTER:
4913 print_job_delete, print_job_pause, print_job_resume,
4916 ****************************************************************************/
4917 BOOL
print_access_check(struct current_user
*user
, int snum
, int access_type
)
4919 SEC_DESC_BUF
*secdesc
= NULL
;
4920 uint32 access_granted
;
4924 TALLOC_CTX
*mem_ctx
= NULL
;
4925 extern struct current_user current_user
;
4927 /* If user is NULL then use the current_user structure */
4930 user
= ¤t_user
;
4932 /* Always allow root or printer admins to do anything */
4934 if (user
->uid
== 0 ||
4935 user_in_list(uidtoname(user
->uid
), lp_printer_admin(snum
), user
->groups
, user
->ngroups
)) {
4939 /* Get printer name */
4941 pname
= PRINTERNAME(snum
);
4943 if (!pname
|| !*pname
) {
4948 /* Get printer security descriptor */
4950 if(!(mem_ctx
= talloc_init("print_access_check"))) {
4955 nt_printing_getsec(mem_ctx
, pname
, &secdesc
);
4957 if (access_type
== JOB_ACCESS_ADMINISTER
) {
4958 SEC_DESC_BUF
*parent_secdesc
= secdesc
;
4960 /* Create a child security descriptor to check permissions
4961 against. This is because print jobs are child objects
4962 objects of a printer. */
4964 secdesc
= se_create_child_secdesc(mem_ctx
, parent_secdesc
->sec
, False
);
4966 /* Now this is the bit that really confuses me. The access
4967 type needs to be changed from JOB_ACCESS_ADMINISTER to
4968 PRINTER_ACCESS_ADMINISTER for this to work. Something
4969 to do with the child (job) object becoming like a
4972 access_type
= PRINTER_ACCESS_ADMINISTER
;
4977 map_printer_permissions(secdesc
->sec
);
4979 result
= se_access_check(secdesc
->sec
, user
->nt_user_token
, access_type
,
4980 &access_granted
, &status
);
4982 DEBUG(4, ("access check was %s\n", result
? "SUCCESS" : "FAILURE"));
4984 talloc_destroy(mem_ctx
);
4992 /****************************************************************************
4993 Check the time parameters allow a print operation.
4994 *****************************************************************************/
4996 BOOL
print_time_access_check(int snum
)
4998 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5000 time_t now
= time(NULL
);
5004 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))))
5007 if (printer
->info_2
->starttime
== 0 && printer
->info_2
->untiltime
== 0)
5011 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
5013 if (mins
>= printer
->info_2
->starttime
&& mins
<= printer
->info_2
->untiltime
)
5016 free_a_printer(&printer
, 2);