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 /****************************************************************************
2041 ****************************************************************************/
2042 static WERROR
update_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
)
2048 TDB_DATA kbuf
, dbuf
;
2051 * in addprinter: no servername and the printer is the name
2052 * in setprinter: servername is \\server
2053 * and printer is \\server\\printer
2055 * Samba manages only local printers.
2056 * we currently don't support things like path=\\other_server\printer
2059 if (info
->servername
[0]!='\0') {
2060 trim_string(info
->printername
, info
->servername
, NULL
);
2061 trim_char(info
->printername
, '\\', '\0');
2062 info
->servername
[0]='\0';
2066 * JFM: one day I'll forget.
2067 * below that's info->portname because that's the SAMBA sharename
2068 * and I made NT 'thinks' it's the portname
2069 * the info->sharename is the thing you can name when you add a printer
2070 * that's the short-name when you create shared printer for 95/98
2071 * So I've made a limitation in SAMBA: you can only have 1 printer model
2072 * behind a SAMBA share.
2080 len
+= tdb_pack(buf
+len
, buflen
-len
, "dddddddddddfffffPfffff",
2083 info
->default_priority
,
2100 info
->printprocessor
,
2104 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
2106 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
2108 if (buflen
!= len
) {
2111 tb
= (char *)Realloc(buf
, len
);
2113 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2123 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, info
->sharename
);
2126 kbuf
.dsize
= strlen(key
)+1;
2130 ret
= (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) == 0? WERR_OK
: WERR_NOMEM
);
2133 if (!W_ERROR_IS_OK(ret
))
2134 DEBUG(8, ("error updating printer to tdb on disk\n"));
2138 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2139 info
->sharename
, info
->drivername
, info
->portname
, len
));
2145 /****************************************************************************
2146 Malloc and return an NT devicemode.
2147 ****************************************************************************/
2149 NT_DEVICEMODE
*construct_nt_devicemode(const fstring default_devicename
)
2152 char adevice
[MAXDEVICENAME
];
2153 NT_DEVICEMODE
*nt_devmode
= (NT_DEVICEMODE
*)malloc(sizeof(NT_DEVICEMODE
));
2155 if (nt_devmode
== NULL
) {
2156 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2160 ZERO_STRUCTP(nt_devmode
);
2162 safe_strcpy(adevice
, default_devicename
, sizeof(adevice
)-1);
2163 fstrcpy(nt_devmode
->devicename
, adevice
);
2165 fstrcpy(nt_devmode
->formname
, "Letter");
2167 nt_devmode
->specversion
= 0x0401;
2168 nt_devmode
->driverversion
= 0x0400;
2169 nt_devmode
->size
= 0x00DC;
2170 nt_devmode
->driverextra
= 0x0000;
2171 nt_devmode
->fields
= FORMNAME
| TTOPTION
| PRINTQUALITY
|
2172 DEFAULTSOURCE
| COPIES
| SCALE
|
2173 PAPERSIZE
| ORIENTATION
;
2174 nt_devmode
->orientation
= 1;
2175 nt_devmode
->papersize
= PAPER_LETTER
;
2176 nt_devmode
->paperlength
= 0;
2177 nt_devmode
->paperwidth
= 0;
2178 nt_devmode
->scale
= 0x64;
2179 nt_devmode
->copies
= 1;
2180 nt_devmode
->defaultsource
= BIN_FORMSOURCE
;
2181 nt_devmode
->printquality
= RES_HIGH
; /* 0x0258 */
2182 nt_devmode
->color
= COLOR_MONOCHROME
;
2183 nt_devmode
->duplex
= DUP_SIMPLEX
;
2184 nt_devmode
->yresolution
= 0;
2185 nt_devmode
->ttoption
= TT_SUBDEV
;
2186 nt_devmode
->collate
= COLLATE_FALSE
;
2187 nt_devmode
->icmmethod
= 0;
2188 nt_devmode
->icmintent
= 0;
2189 nt_devmode
->mediatype
= 0;
2190 nt_devmode
->dithertype
= 0;
2192 /* non utilisés par un driver d'imprimante */
2193 nt_devmode
->logpixels
= 0;
2194 nt_devmode
->bitsperpel
= 0;
2195 nt_devmode
->pelswidth
= 0;
2196 nt_devmode
->pelsheight
= 0;
2197 nt_devmode
->displayflags
= 0;
2198 nt_devmode
->displayfrequency
= 0;
2199 nt_devmode
->reserved1
= 0;
2200 nt_devmode
->reserved2
= 0;
2201 nt_devmode
->panningwidth
= 0;
2202 nt_devmode
->panningheight
= 0;
2204 nt_devmode
->private = NULL
;
2208 /****************************************************************************
2209 Deepcopy an NT devicemode.
2210 ****************************************************************************/
2212 NT_DEVICEMODE
*dup_nt_devicemode(NT_DEVICEMODE
*nt_devicemode
)
2214 NT_DEVICEMODE
*new_nt_devicemode
= NULL
;
2216 if ( !nt_devicemode
)
2219 if ((new_nt_devicemode
= (NT_DEVICEMODE
*)memdup(nt_devicemode
, sizeof(NT_DEVICEMODE
))) == NULL
) {
2220 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2224 new_nt_devicemode
->private = NULL
;
2225 if (nt_devicemode
->private != NULL
) {
2226 if ((new_nt_devicemode
->private = memdup(nt_devicemode
->private, nt_devicemode
->driverextra
)) == NULL
) {
2227 SAFE_FREE(new_nt_devicemode
);
2228 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2233 return new_nt_devicemode
;
2236 /****************************************************************************
2237 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2238 ****************************************************************************/
2240 void free_nt_devicemode(NT_DEVICEMODE
**devmode_ptr
)
2242 NT_DEVICEMODE
*nt_devmode
= *devmode_ptr
;
2244 if(nt_devmode
== NULL
)
2247 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2249 SAFE_FREE(nt_devmode
->private);
2250 SAFE_FREE(*devmode_ptr
);
2253 /****************************************************************************
2254 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2255 ****************************************************************************/
2256 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
)
2258 NT_PRINTER_INFO_LEVEL_2
*info
= *info_ptr
;
2259 NT_PRINTER_DATA
*data
;
2265 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2267 free_nt_devicemode(&info
->devmode
);
2269 /* clean up all registry keys */
2272 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2273 SAFE_FREE( data
->keys
[i
].name
);
2274 regval_ctr_destroy( &data
->keys
[i
].values
);
2276 SAFE_FREE( data
->keys
);
2278 /* finally the top level structure */
2280 SAFE_FREE( *info_ptr
);
2284 /****************************************************************************
2285 ****************************************************************************/
2286 int unpack_devicemode(NT_DEVICEMODE
**nt_devmode
, char *buf
, int buflen
)
2290 NT_DEVICEMODE devmode
;
2292 ZERO_STRUCT(devmode
);
2294 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2296 if (!*nt_devmode
) return len
;
2298 len
+= tdb_unpack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2302 &devmode
.specversion
,
2303 &devmode
.driverversion
,
2305 &devmode
.driverextra
,
2306 &devmode
.orientation
,
2308 &devmode
.paperlength
,
2309 &devmode
.paperwidth
,
2312 &devmode
.defaultsource
,
2313 &devmode
.printquality
,
2316 &devmode
.yresolution
,
2322 &devmode
.bitsperpel
,
2324 &devmode
.pelsheight
,
2325 &devmode
.displayflags
,
2326 &devmode
.displayfrequency
,
2330 &devmode
.dithertype
,
2333 &devmode
.panningwidth
,
2334 &devmode
.panningheight
,
2337 if (devmode
.private) {
2338 /* the len in tdb_unpack is an int value and
2339 * devmode.driverextra is only a short
2341 len
+= tdb_unpack(buf
+len
, buflen
-len
, "B", &extra_len
, &devmode
.private);
2342 devmode
.driverextra
=(uint16
)extra_len
;
2344 /* check to catch an invalid TDB entry so we don't segfault */
2345 if (devmode
.driverextra
== 0) {
2346 devmode
.private = NULL
;
2350 *nt_devmode
= (NT_DEVICEMODE
*)memdup(&devmode
, sizeof(devmode
));
2352 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode
.devicename
, devmode
.formname
));
2353 if (devmode
.private)
2354 DEBUG(8,("with a private section of %d bytes\n", devmode
.driverextra
));
2359 /****************************************************************************
2360 Allocate and initialize a new slot.
2361 ***************************************************************************/
2363 static int add_new_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2368 if ( !data
|| !name
)
2371 /* allocate another slot in the NT_PRINTER_KEY array */
2373 d
= Realloc( data
->keys
, sizeof(NT_PRINTER_KEY
)*(data
->num_keys
+1) );
2377 key_index
= data
->num_keys
;
2379 /* initialze new key */
2382 data
->keys
[key_index
].name
= strdup( name
);
2384 ZERO_STRUCTP( &data
->keys
[key_index
].values
);
2386 regval_ctr_init( &data
->keys
[key_index
].values
);
2388 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name
));
2393 /****************************************************************************
2394 search for a registry key name in the existing printer data
2395 ***************************************************************************/
2397 int lookup_printerkey( NT_PRINTER_DATA
*data
, const char *name
)
2402 if ( !data
|| !name
)
2405 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name
));
2407 /* loop over all existing keys */
2409 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2410 if ( strequal(data
->keys
[i
].name
, name
) ) {
2411 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name
));
2421 /****************************************************************************
2422 ***************************************************************************/
2424 uint32
get_printer_subkeys( NT_PRINTER_DATA
*data
, const char* key
, fstring
**subkeys
)
2428 int num_subkeys
= 0;
2430 fstring
*ptr
, *subkeys_ptr
= NULL
;
2436 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2437 if ( StrnCaseCmp(data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2438 /* match sure it is a subkey and not the key itself */
2440 key_len
= strlen( key
);
2441 if ( strlen(data
->keys
[i
].name
) == key_len
)
2444 /* get subkey path */
2446 p
= data
->keys
[i
].name
+ key_len
;
2449 fstrcpy( subkeyname
, p
);
2450 if ( (p
= strchr( subkeyname
, '\\' )) )
2453 /* don't add a key more than once */
2455 for ( j
=0; j
<num_subkeys
; j
++ ) {
2456 if ( strequal( subkeys_ptr
[j
], subkeyname
) )
2460 if ( j
!= num_subkeys
)
2463 /* found a match, so allocate space and copy the name */
2465 if ( !(ptr
= Realloc( subkeys_ptr
, (num_subkeys
+2)*sizeof(fstring
))) ) {
2466 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2468 SAFE_FREE( subkeys
);
2473 fstrcpy( subkeys_ptr
[num_subkeys
], subkeyname
);
2479 /* tag of the end */
2482 fstrcpy(subkeys_ptr
[num_subkeys
], "" );
2484 *subkeys
= subkeys_ptr
;
2490 static void map_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2493 smb_ucs2_t conv_str
[1024];
2496 regval_ctr_delvalue(ctr
, val_name
);
2497 str_size
= push_ucs2(NULL
, conv_str
, sz
, sizeof(conv_str
),
2498 STR_TERMINATE
| STR_NOALIGN
);
2499 regval_ctr_addvalue(ctr
, val_name
, REG_SZ
,
2500 (char *) conv_str
, str_size
);
2503 static void map_dword_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2506 regval_ctr_delvalue(ctr
, val_name
);
2507 regval_ctr_addvalue(ctr
, val_name
, REG_DWORD
,
2508 (char *) &dword
, sizeof(dword
));
2511 static void map_bool_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2514 uint8 bin_bool
= (b
? 1 : 0);
2515 regval_ctr_delvalue(ctr
, val_name
);
2516 regval_ctr_addvalue(ctr
, val_name
, REG_BINARY
,
2517 (char *) &bin_bool
, sizeof(bin_bool
));
2520 static void map_single_multi_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2521 const char *multi_sz
)
2523 smb_ucs2_t
*conv_strs
= NULL
;
2526 /* a multi-sz has to have a null string terminator, i.e., the last
2527 string must be followed by two nulls */
2528 str_size
= (strlen(multi_sz
) + 2) * sizeof(smb_ucs2_t
);
2529 conv_strs
= calloc(str_size
, 1);
2531 push_ucs2(NULL
, conv_strs
, multi_sz
, str_size
,
2532 STR_TERMINATE
| STR_NOALIGN
);
2534 regval_ctr_delvalue(ctr
, val_name
);
2535 regval_ctr_addvalue(ctr
, val_name
, REG_MULTI_SZ
,
2536 (char *) conv_strs
, str_size
);
2537 safe_free(conv_strs
);
2541 /****************************************************************************
2542 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2544 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2545 * @return BOOL indicating success or failure
2546 ***************************************************************************/
2548 static BOOL
map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2
*info2
)
2550 REGVAL_CTR
*ctr
= NULL
;
2552 char *allocated_string
= NULL
;
2553 const char *ascii_str
;
2556 if ((i
= lookup_printerkey(&info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2557 i
= add_new_printer_key(&info2
->data
, SPOOL_DSSPOOLER_KEY
);
2558 ctr
= &info2
->data
.keys
[i
].values
;
2560 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTERNAME
, info2
->sharename
);
2561 map_sz_into_ctr(ctr
, SPOOL_REG_SHORTSERVERNAME
, global_myname());
2563 get_mydnsfullname(longname
);
2564 map_sz_into_ctr(ctr
, SPOOL_REG_SERVERNAME
, longname
);
2566 asprintf(&allocated_string
, "\\\\%s\\%s", longname
, info2
->sharename
);
2567 map_sz_into_ctr(ctr
, SPOOL_REG_UNCNAME
, allocated_string
);
2568 SAFE_FREE(allocated_string
);
2570 map_dword_into_ctr(ctr
, SPOOL_REG_VERSIONNUMBER
, 4);
2571 map_sz_into_ctr(ctr
, SPOOL_REG_DRIVERNAME
, info2
->drivername
);
2572 map_sz_into_ctr(ctr
, SPOOL_REG_LOCATION
, info2
->location
);
2573 map_sz_into_ctr(ctr
, SPOOL_REG_DESCRIPTION
, info2
->comment
);
2574 map_single_multi_sz_into_ctr(ctr
, SPOOL_REG_PORTNAME
, info2
->portname
);
2575 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSEPARATORFILE
, info2
->sepfile
);
2576 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTSTARTTIME
, info2
->starttime
);
2577 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTENDTIME
, info2
->untiltime
);
2578 map_dword_into_ctr(ctr
, SPOOL_REG_PRIORITY
, info2
->priority
);
2580 map_bool_into_ctr(ctr
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
2581 (info2
->attributes
&
2582 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
2584 switch (info2
->attributes
& 0x3) {
2586 ascii_str
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
2589 ascii_str
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
2592 ascii_str
= SPOOL_REGVAL_PRINTDIRECT
;
2595 ascii_str
= "unknown";
2597 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSPOOLING
, ascii_str
);
2602 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2
*info2
,
2606 REGVAL_CTR
*ctr
=NULL
;
2608 /* find the DsSpooler key */
2609 if ((i
= lookup_printerkey(&info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2610 i
= add_new_printer_key(&info2
->data
, SPOOL_DSSPOOLER_KEY
);
2611 ctr
= &info2
->data
.keys
[i
].values
;
2613 regval_ctr_delvalue(ctr
, "objectGUID");
2614 regval_ctr_addvalue(ctr
, "objectGUID", REG_BINARY
,
2615 (char *) &guid
, sizeof(struct uuid
));
2618 static WERROR
publish_it(NT_PRINTER_INFO_LEVEL
*printer
)
2621 TALLOC_CTX
*ctx
= talloc_init("publish_it");
2622 ADS_MODLIST mods
= ads_init_mods(ctx
);
2623 char *prt_dn
= NULL
, *srv_dn
, *srv_cn_0
;
2624 char *srv_dn_utf8
, **srv_cn_utf8
;
2627 const char *attrs
[] = {"objectGUID", NULL
};
2629 WERROR win_rc
= WERR_OK
;
2632 /* set the DsSpooler info and attributes */
2633 if (!(map_nt_printer_info2_to_dsspooler(printer
->info_2
)))
2635 printer
->info_2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
2636 win_rc
= mod_a_printer(*printer
, 2);
2637 if (!W_ERROR_IS_OK(win_rc
)) {
2638 DEBUG(3, ("err %d saving data\n",
2639 W_ERROR_V(win_rc
)));
2643 /* Build the ads mods */
2644 get_local_printer_publishing_data(ctx
, &mods
,
2645 &printer
->info_2
->data
);
2646 ads_mod_str(ctx
, &mods
, SPOOL_REG_PRINTERNAME
,
2647 printer
->info_2
->sharename
);
2649 /* initial ads structure */
2651 ads
= ads_init(NULL
, NULL
, NULL
);
2653 DEBUG(3, ("ads_init() failed\n"));
2654 return WERR_SERVER_UNAVAILABLE
;
2656 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
2657 SAFE_FREE(ads
->auth
.password
);
2658 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
2661 /* ads_connect() will find the DC for us */
2662 ads_rc
= ads_connect(ads
);
2663 if (!ADS_ERR_OK(ads_rc
)) {
2664 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
2666 return WERR_ACCESS_DENIED
;
2669 /* figure out where to publish */
2670 ads_find_machine_acct(ads
, &res
, global_myname());
2672 /* We use ldap_get_dn here as we need the answer
2673 * in utf8 to call ldap_explode_dn(). JRA. */
2675 srv_dn_utf8
= ldap_get_dn(ads
->ld
, res
);
2678 return WERR_SERVER_UNAVAILABLE
;
2680 ads_msgfree(ads
, res
);
2681 srv_cn_utf8
= ldap_explode_dn(srv_dn_utf8
, 1);
2683 ldap_memfree(srv_dn_utf8
);
2685 return WERR_SERVER_UNAVAILABLE
;
2687 /* Now convert to CH_UNIX. */
2688 if (pull_utf8_allocate(&srv_dn
, srv_dn_utf8
) == (size_t)-1) {
2689 ldap_memfree(srv_dn_utf8
);
2690 ldap_memfree(srv_cn_utf8
);
2692 return WERR_SERVER_UNAVAILABLE
;
2694 if (pull_utf8_allocate(&srv_cn_0
, srv_cn_utf8
[0]) == (size_t)-1) {
2695 ldap_memfree(srv_dn_utf8
);
2696 ldap_memfree(srv_cn_utf8
);
2699 return WERR_SERVER_UNAVAILABLE
;
2702 ldap_memfree(srv_dn_utf8
);
2703 ldap_memfree(srv_cn_utf8
);
2705 asprintf(&prt_dn
, "cn=%s-%s,%s", srv_cn_0
,
2706 printer
->info_2
->sharename
, srv_dn
);
2709 SAFE_FREE(srv_cn_0
);
2712 ads_rc
= ads_add_printer_entry(ads
, prt_dn
, ctx
, &mods
);
2713 if (LDAP_ALREADY_EXISTS
== ads_rc
.err
.rc
)
2714 ads_rc
= ads_mod_printer_entry(ads
, prt_dn
, ctx
,&mods
);
2716 /* retreive the guid and store it locally */
2717 if (ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
2718 ads_pull_guid(ads
, res
, &guid
);
2719 ads_msgfree(ads
, res
);
2720 store_printer_guid(printer
->info_2
, guid
);
2721 win_rc
= mod_a_printer(*printer
, 2);
2730 WERROR
unpublish_it(NT_PRINTER_INFO_LEVEL
*printer
)
2735 char *prt_dn
= NULL
;
2738 printer
->info_2
->attributes
^= PRINTER_ATTRIBUTE_PUBLISHED
;
2739 win_rc
= mod_a_printer(*printer
, 2);
2740 if (!W_ERROR_IS_OK(win_rc
)) {
2741 DEBUG(3, ("err %d saving data\n",
2742 W_ERROR_V(win_rc
)));
2746 ads
= ads_init(NULL
, NULL
, NULL
);
2748 DEBUG(3, ("ads_init() failed\n"));
2749 return WERR_SERVER_UNAVAILABLE
;
2751 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
2752 SAFE_FREE(ads
->auth
.password
);
2753 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
2756 /* ads_connect() will find the DC for us */
2757 ads_rc
= ads_connect(ads
);
2758 if (!ADS_ERR_OK(ads_rc
)) {
2759 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
2761 return WERR_ACCESS_DENIED
;
2764 /* remove the printer from the directory */
2765 ads_rc
= ads_find_printer_on_server(ads
, &res
,
2766 printer
->info_2
->sharename
, global_myname());
2767 if (ADS_ERR_OK(ads_rc
) && ads_count_replies(ads
, res
)) {
2768 prt_dn
= ads_get_dn(ads
, res
);
2769 ads_msgfree(ads
, res
);
2770 ads_rc
= ads_del_dn(ads
, prt_dn
);
2771 ads_memfree(ads
, prt_dn
);
2778 /****************************************************************************
2779 * Publish a printer in the directory
2781 * @param snum describing printer service
2782 * @return WERROR indicating status of publishing
2783 ***************************************************************************/
2785 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
2787 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2790 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
2791 if (!W_ERROR_IS_OK(win_rc
))
2795 case SPOOL_DS_PUBLISH
:
2796 case SPOOL_DS_UPDATE
:
2797 win_rc
= publish_it(printer
);
2799 case SPOOL_DS_UNPUBLISH
:
2800 win_rc
= unpublish_it(printer
);
2803 win_rc
= WERR_NOT_SUPPORTED
;
2807 free_a_printer(&printer
, 2);
2811 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
,
2814 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2816 REGISTRY_VALUE
*guid_val
;
2821 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
2822 if (!W_ERROR_IS_OK(win_rc
))
2825 if (!(printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
))
2828 if ((i
= lookup_printerkey(&printer
->info_2
->data
,
2829 SPOOL_DSSPOOLER_KEY
)) < 0)
2832 if (!(ctr
= &printer
->info_2
->data
.keys
[i
].values
)) {
2836 if (!(guid_val
= regval_ctr_getvalue(ctr
, "objectGUID"))) {
2840 if (regval_size(guid_val
) == sizeof(struct uuid
))
2841 memcpy(guid
, regval_data_p(guid_val
), sizeof(struct uuid
));
2847 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
2851 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
,
2857 /****************************************************************************
2858 ***************************************************************************/
2860 WERROR
delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
)
2862 NT_PRINTER_DATA
*data
;
2864 int removed_keys
= 0;
2868 empty_slot
= data
->num_keys
;
2871 return WERR_INVALID_PARAM
;
2873 /* remove all keys */
2875 if ( !strlen(key
) ) {
2876 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2877 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2878 data
->keys
[i
].name
));
2880 SAFE_FREE( data
->keys
[i
].name
);
2881 regval_ctr_destroy( &data
->keys
[i
].values
);
2884 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2887 SAFE_FREE( data
->keys
);
2888 ZERO_STRUCTP( data
);
2893 /* remove a specific key (and all subkeys) */
2895 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2896 if ( StrnCaseCmp( data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2897 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2898 data
->keys
[i
].name
));
2900 SAFE_FREE( data
->keys
[i
].name
);
2901 regval_ctr_destroy( &data
->keys
[i
].values
);
2903 /* mark the slot as empty */
2905 ZERO_STRUCTP( &data
->keys
[i
] );
2909 /* find the first empty slot */
2911 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2912 if ( !data
->keys
[i
].name
) {
2919 if ( i
== data
->num_keys
)
2920 /* nothing was removed */
2921 return WERR_INVALID_PARAM
;
2923 /* move everything down */
2925 for ( i
=empty_slot
+1; i
<data
->num_keys
; i
++ ) {
2926 if ( data
->keys
[i
].name
) {
2927 memcpy( &data
->keys
[empty_slot
], &data
->keys
[i
], sizeof(NT_PRINTER_KEY
) );
2928 ZERO_STRUCTP( &data
->keys
[i
] );
2936 data
->num_keys
-= removed_keys
;
2938 /* sanity check to see if anything is left */
2940 if ( !data
->num_keys
) {
2941 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2
->printername
));
2943 SAFE_FREE( data
->keys
);
2944 ZERO_STRUCTP( data
);
2950 /****************************************************************************
2951 ***************************************************************************/
2953 WERROR
delete_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
2955 WERROR result
= WERR_OK
;
2958 /* we must have names on non-zero length */
2960 if ( !key
|| !*key
|| !value
|| !*value
)
2961 return WERR_INVALID_NAME
;
2963 /* find the printer key first */
2965 key_index
= lookup_printerkey( &p2
->data
, key
);
2966 if ( key_index
== -1 )
2969 /* make sure the value exists so we can return the correct error code */
2971 if ( !regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
) )
2972 return WERR_BADFILE
;
2974 regval_ctr_delvalue( &p2
->data
.keys
[key_index
].values
, value
);
2976 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2982 /****************************************************************************
2983 ***************************************************************************/
2985 WERROR
add_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
,
2986 uint32 type
, uint8
*data
, int real_len
)
2988 WERROR result
= WERR_OK
;
2991 /* we must have names on non-zero length */
2993 if ( !key
|| !*key
|| !value
|| !*value
)
2994 return WERR_INVALID_NAME
;
2996 /* find the printer key first */
2998 key_index
= lookup_printerkey( &p2
->data
, key
);
2999 if ( key_index
== -1 )
3000 key_index
= add_new_printer_key( &p2
->data
, key
);
3002 if ( key_index
== -1 )
3005 regval_ctr_addvalue( &p2
->data
.keys
[key_index
].values
, value
,
3006 type
, (const char *)data
, real_len
);
3008 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3009 key
, value
, type
, real_len
));
3014 /****************************************************************************
3015 ***************************************************************************/
3017 REGISTRY_VALUE
* get_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3021 if ( (key_index
= lookup_printerkey( &p2
->data
, key
)) == -1 )
3024 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3027 return regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
);
3030 /****************************************************************************
3031 Unpack a list of registry values frem the TDB
3032 ***************************************************************************/
3034 static int unpack_values(NT_PRINTER_DATA
*printer_data
, char *buf
, int buflen
)
3038 pstring string
, valuename
, keyname
;
3042 REGISTRY_VALUE
*regval_p
;
3045 /* add the "PrinterDriverData" key first for performance reasons */
3047 add_new_printer_key( printer_data
, SPOOL_PRINTERDATA_KEY
);
3049 /* loop and unpack the rest of the registry values */
3053 /* check to see if there are any more registry values */
3056 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", ®val_p
);
3060 /* unpack the next regval */
3062 len
+= tdb_unpack(buf
+len
, buflen
-len
, "fdB",
3069 * break of the keyname from the value name.
3070 * Should only be one '\' in the string returned.
3073 str
= strrchr( string
, '\\');
3075 /* Put in "PrinterDriverData" is no key specified */
3078 pstrcpy( keyname
, SPOOL_PRINTERDATA_KEY
);
3079 pstrcpy( valuename
, string
);
3083 pstrcpy( keyname
, string
);
3084 pstrcpy( valuename
, str
+1 );
3087 /* see if we need a new key */
3089 if ( (key_index
=lookup_printerkey( printer_data
, keyname
)) == -1 )
3090 key_index
= add_new_printer_key( printer_data
, keyname
);
3092 if ( key_index
== -1 ) {
3093 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3098 /* add the new value */
3100 regval_ctr_addvalue( &printer_data
->keys
[key_index
].values
, valuename
, type
, (const char *)data_p
, size
);
3102 SAFE_FREE(data_p
); /* 'B' option to tdbpack does a malloc() */
3104 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname
, valuename
, size
));
3110 /****************************************************************************
3111 ***************************************************************************/
3113 static void map_to_os2_driver(fstring drivername
)
3115 static BOOL initialised
=False
;
3116 static fstring last_from
,last_to
;
3117 char *mapfile
= lp_os2_driver_map();
3118 char **lines
= NULL
;
3122 if (!strlen(drivername
))
3129 *last_from
= *last_to
= 0;
3133 if (strequal(drivername
,last_from
)) {
3134 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,last_to
));
3135 fstrcpy(drivername
,last_to
);
3139 lines
= file_lines_load(mapfile
, &numlines
);
3140 if (numlines
== 0) {
3141 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile
));
3145 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
3147 for( i
= 0; i
< numlines
; i
++) {
3148 char *nt_name
= lines
[i
];
3149 char *os2_name
= strchr(nt_name
,'=');
3156 while (isspace(*nt_name
))
3159 if (!*nt_name
|| strchr("#;",*nt_name
))
3163 int l
= strlen(nt_name
);
3164 while (l
&& isspace(nt_name
[l
-1])) {
3170 while (isspace(*os2_name
))
3174 int l
= strlen(os2_name
);
3175 while (l
&& isspace(os2_name
[l
-1])) {
3181 if (strequal(nt_name
,drivername
)) {
3182 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername
,os2_name
));
3183 fstrcpy(last_from
,drivername
);
3184 fstrcpy(last_to
,os2_name
);
3185 fstrcpy(drivername
,os2_name
);
3186 file_lines_free(lines
);
3191 file_lines_free(lines
);
3194 /****************************************************************************
3195 Get a default printer info 2 struct.
3196 ****************************************************************************/
3197 static WERROR
get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, const char *sharename
)
3200 NT_PRINTER_INFO_LEVEL_2 info
;
3204 snum
= lp_servicenumber(sharename
);
3206 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", get_called_name());
3207 slprintf(info
.printername
, sizeof(info
.printername
)-1, "\\\\%s\\%s",
3208 get_called_name(), sharename
);
3209 fstrcpy(info
.sharename
, sharename
);
3210 fstrcpy(info
.portname
, SAMBA_PRINTER_PORT_NAME
);
3212 /* by setting the driver name to an empty string, a local NT admin
3213 can now run the **local** APW to install a local printer driver
3214 for a Samba shared printer in 2.2. Without this, drivers **must** be
3215 installed on the Samba server for NT clients --jerry */
3216 #if 0 /* JERRY --do not uncomment-- */
3217 if (!*info
.drivername
)
3218 fstrcpy(info
.drivername
, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3222 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info
.drivername
));
3224 pstrcpy(info
.comment
, "");
3225 fstrcpy(info
.printprocessor
, "winprint");
3226 fstrcpy(info
.datatype
, "RAW");
3228 info
.attributes
= PRINTER_ATTRIBUTE_SAMBA
;
3230 info
.starttime
= 0; /* Minutes since 12:00am GMT */
3231 info
.untiltime
= 0; /* Minutes since 12:00am GMT */
3233 info
.default_priority
= 1;
3234 info
.setuptime
= (uint32
)time(NULL
);
3237 * I changed this as I think it is better to have a generic
3238 * DEVMODE than to crash Win2k explorer.exe --jerry
3239 * See the HP Deskjet 990c Win2k drivers for an example.
3241 * However the default devmode appears to cause problems
3242 * with the HP CLJ 8500 PCL driver. Hence the addition of
3243 * the "default devmode" parameter --jerry 22/01/2002
3246 if (lp_default_devmode(snum
)) {
3247 if ((info
.devmode
= construct_nt_devicemode(info
.printername
)) == NULL
)
3251 info
.devmode
= NULL
;
3254 /* This will get the current RPC talloc context, but we should be
3255 passing this as a parameter... fixme... JRA ! */
3257 if (!nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
))
3260 *info_ptr
= (NT_PRINTER_INFO_LEVEL_2
*)memdup(&info
, sizeof(info
));
3262 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3270 free_nt_devicemode(&info
.devmode
);
3271 return WERR_ACCESS_DENIED
;
3274 /****************************************************************************
3275 ****************************************************************************/
3276 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, const char *sharename
)
3279 NT_PRINTER_INFO_LEVEL_2 info
;
3281 TDB_DATA kbuf
, dbuf
;
3282 fstring printername
;
3283 char adevice
[MAXDEVICENAME
];
3287 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
3290 kbuf
.dsize
= strlen(key
)+1;
3292 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
3294 return get_a_printer_2_default(info_ptr
, sharename
);
3296 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "dddddddddddfffffPfffff",
3299 &info
.default_priority
,
3316 info
.printprocessor
,
3320 /* Samba has to have shared raw drivers. */
3321 info
.attributes
= PRINTER_ATTRIBUTE_SAMBA
;
3323 /* Restore the stripped strings. */
3324 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", get_called_name());
3325 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", get_called_name(),
3327 fstrcpy(info
.printername
, printername
);
3329 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3332 * Some client drivers freak out if there is a NULL devmode
3333 * (probably the driver is not checking before accessing
3334 * the devmode pointer) --jerry
3336 * See comments in get_a_printer_2_default()
3339 if (lp_default_devmode(lp_servicenumber(sharename
)) && !info
.devmode
) {
3340 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3342 info
.devmode
= construct_nt_devicemode(printername
);
3345 safe_strcpy(adevice
, info
.printername
, sizeof(adevice
)-1);
3347 fstrcpy(info
.devmode
->devicename
, adevice
);
3350 len
+= unpack_values( &info
.data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3352 /* This will get the current RPC talloc context, but we should be
3353 passing this as a parameter... fixme... JRA ! */
3355 nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
);
3357 /* Fix for OS/2 drivers. */
3359 if (get_remote_arch() == RA_OS2
)
3360 map_to_os2_driver(info
.drivername
);
3362 SAFE_FREE(dbuf
.dptr
);
3363 *info_ptr
=memdup(&info
, sizeof(info
));
3365 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3366 sharename
, info
.printername
, info
.drivername
));
3371 /****************************************************************************
3372 Debugging function, dump at level 6 the struct in the logs.
3373 ****************************************************************************/
3374 static uint32
dump_a_printer(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3377 NT_PRINTER_INFO_LEVEL_2
*info2
;
3379 DEBUG(106,("Dumping printer at level [%d]\n", level
));
3384 if (printer
.info_2
== NULL
)
3388 info2
=printer
.info_2
;
3390 DEBUGADD(106,("attributes:[%d]\n", info2
->attributes
));
3391 DEBUGADD(106,("priority:[%d]\n", info2
->priority
));
3392 DEBUGADD(106,("default_priority:[%d]\n", info2
->default_priority
));
3393 DEBUGADD(106,("starttime:[%d]\n", info2
->starttime
));
3394 DEBUGADD(106,("untiltime:[%d]\n", info2
->untiltime
));
3395 DEBUGADD(106,("status:[%d]\n", info2
->status
));
3396 DEBUGADD(106,("cjobs:[%d]\n", info2
->cjobs
));
3397 DEBUGADD(106,("averageppm:[%d]\n", info2
->averageppm
));
3398 DEBUGADD(106,("changeid:[%d]\n", info2
->changeid
));
3399 DEBUGADD(106,("c_setprinter:[%d]\n", info2
->c_setprinter
));
3400 DEBUGADD(106,("setuptime:[%d]\n", info2
->setuptime
));
3402 DEBUGADD(106,("servername:[%s]\n", info2
->servername
));
3403 DEBUGADD(106,("printername:[%s]\n", info2
->printername
));
3404 DEBUGADD(106,("sharename:[%s]\n", info2
->sharename
));
3405 DEBUGADD(106,("portname:[%s]\n", info2
->portname
));
3406 DEBUGADD(106,("drivername:[%s]\n", info2
->drivername
));
3407 DEBUGADD(106,("comment:[%s]\n", info2
->comment
));
3408 DEBUGADD(106,("location:[%s]\n", info2
->location
));
3409 DEBUGADD(106,("sepfile:[%s]\n", info2
->sepfile
));
3410 DEBUGADD(106,("printprocessor:[%s]\n", info2
->printprocessor
));
3411 DEBUGADD(106,("datatype:[%s]\n", info2
->datatype
));
3412 DEBUGADD(106,("parameters:[%s]\n", info2
->parameters
));
3418 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level
));
3426 /****************************************************************************
3427 Update the changeid time.
3428 This is SO NASTY as some drivers need this to change, others need it
3429 static. This value will change every second, and I must hope that this
3430 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3432 ****************************************************************************/
3434 static uint32
rev_changeid(void)
3438 get_process_uptime(&tv
);
3441 /* Return changeid as msec since spooler restart */
3442 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
3445 * This setting seems to work well but is too untested
3446 * to replace the above calculation. Left in for experiementation
3447 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3449 return tv
.tv_sec
* 10 + tv
.tv_usec
/ 100000;
3454 * The function below are the high level ones.
3455 * only those ones must be called from the spoolss code.
3459 /****************************************************************************
3460 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3461 ****************************************************************************/
3463 WERROR
mod_a_printer(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3467 dump_a_printer(printer
, level
);
3470 * invalidate cache for all open handles to this printer.
3471 * cache for a given handle will be updated on the next
3475 invalidate_printer_hnd_cache( printer
.info_2
->sharename
);
3481 * Update the changestamp. Emperical tests show that the
3482 * ChangeID is always updated,but c_setprinter is
3483 * global spooler variable (not per printer).
3486 /* ChangeID **must** be increasing over the lifetime
3487 of client's spoolss service in order for the
3488 client's cache to show updates */
3490 printer
.info_2
->changeid
= rev_changeid();
3493 * Because one day someone will ask:
3494 * NT->NT An admin connection to a remote
3495 * printer show changes imeediately in
3496 * the properities dialog
3498 * A non-admin connection will only show the
3499 * changes after viewing the properites page
3500 * 2 times. Seems to be related to a
3501 * race condition in the client between the spooler
3502 * updating the local cache and the Explorer.exe GUI
3503 * actually displaying the properties.
3505 * This is fixed in Win2k. admin/non-admin
3506 * connections both display changes immediately.
3511 result
=update_a_printer_2(printer
.info_2
);
3516 result
=WERR_UNKNOWN_LEVEL
;
3523 /****************************************************************************
3524 Initialize printer devmode & data with previously saved driver init values.
3525 ****************************************************************************/
3527 static BOOL
set_driver_init_2( NT_PRINTER_INFO_LEVEL_2
*info_ptr
)
3531 TDB_DATA kbuf
, dbuf
;
3532 NT_PRINTER_INFO_LEVEL_2 info
;
3538 * Delete any printer data 'values' already set. When called for driver
3539 * replace, there will generally be some, but during an add printer, there
3540 * should not be any (if there are delete them).
3543 delete_all_printer_data( info_ptr
, "" );
3545 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info_ptr
->drivername
);
3548 kbuf
.dsize
= strlen(key
)+1;
3550 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
3553 * When changing to a driver that has no init info in the tdb, remove
3554 * the previous drivers init info and leave the new on blank.
3556 free_nt_devicemode(&info_ptr
->devmode
);
3561 * Get the saved DEVMODE..
3564 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3567 * The saved DEVMODE contains the devicename from the printer used during
3568 * the initialization save. Change it to reflect the new printer.
3571 if ( info
.devmode
) {
3572 ZERO_STRUCT(info
.devmode
->devicename
);
3573 fstrcpy(info
.devmode
->devicename
, info_ptr
->printername
);
3577 * NT/2k does not change out the entire DeviceMode of a printer
3578 * when changing the driver. Only the driverextra, private, &
3579 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3581 * Later examination revealed that Windows NT/2k does reset the
3582 * the printer's device mode, bit **only** when you change a
3583 * property of the device mode such as the page orientation.
3588 /* Bind the saved DEVMODE to the new the printer */
3590 free_nt_devicemode(&info_ptr
->devmode
);
3591 info_ptr
->devmode
= info
.devmode
;
3593 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3594 info_ptr
->printername
, info_ptr
->devmode
?"VALID":"NULL", info_ptr
->drivername
));
3596 /* Add the printer data 'values' to the new printer */
3598 len
+= unpack_values( &info_ptr
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3601 SAFE_FREE(dbuf
.dptr
);
3606 /****************************************************************************
3607 Initialize printer devmode & data with previously saved driver init values.
3608 When a printer is created using AddPrinter, the drivername bound to the
3609 printer is used to lookup previously saved driver initialization info, which
3610 is bound to the new printer.
3611 ****************************************************************************/
3613 BOOL
set_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3615 BOOL result
= False
;
3619 result
= set_driver_init_2(printer
->info_2
);
3623 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3631 /****************************************************************************
3632 Delete driver init data stored for a specified driver
3633 ****************************************************************************/
3635 BOOL
del_driver_init(char *drivername
)
3640 if (!drivername
|| !*drivername
) {
3641 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3645 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, drivername
);
3648 kbuf
.dsize
= strlen(key
)+1;
3650 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername
));
3652 return (tdb_delete(tdb_drivers
, kbuf
) == 0);
3655 /****************************************************************************
3656 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3657 in the tdb. Note: this is different from the driver entry and the printer
3658 entry. There should be a single driver init entry for each driver regardless
3659 of whether it was installed from NT or 2K. Technically, they should be
3660 different, but they work out to the same struct.
3661 ****************************************************************************/
3663 static uint32
update_driver_init_2(NT_PRINTER_INFO_LEVEL_2
*info
)
3667 int buflen
, len
, ret
;
3668 TDB_DATA kbuf
, dbuf
;
3675 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
3677 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
3679 if (buflen
!= len
) {
3682 tb
= (char *)Realloc(buf
, len
);
3684 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3694 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info
->drivername
);
3697 kbuf
.dsize
= strlen(key
)+1;
3701 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
3705 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3709 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3710 info
->sharename
, info
->drivername
));
3715 /****************************************************************************
3716 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3717 ****************************************************************************/
3719 uint32
update_driver_init(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3723 dump_a_printer(printer
, level
);
3727 result
= update_driver_init_2(printer
.info_2
);
3737 /****************************************************************************
3738 Convert the printer data value, a REG_BINARY array, into an initialization
3739 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3740 got to keep the endians happy :).
3741 ****************************************************************************/
3743 static BOOL
convert_driver_init( TALLOC_CTX
*ctx
, NT_DEVICEMODE
*nt_devmode
, uint8
*data
, uint32 data_len
)
3745 BOOL result
= False
;
3749 ZERO_STRUCT(devmode
);
3751 prs_init(&ps
, 0, ctx
, UNMARSHALL
);
3752 ps
.data_p
= (char *)data
;
3753 ps
.buffer_size
= data_len
;
3755 if (spoolss_io_devmode("phantom DEVMODE", &ps
, 0, &devmode
))
3756 result
= convert_devicemode("", &devmode
, &nt_devmode
);
3758 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3763 /****************************************************************************
3764 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3766 1. Use the driver's config DLL to this UNC printername and:
3767 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3768 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3769 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3771 The last step triggers saving the "driver initialization" information for
3772 this printer into the tdb. Later, new printers that use this driver will
3773 have this initialization information bound to them. This simulates the
3774 driver initialization, as if it had run on the Samba server (as it would
3777 The Win32 client side code requirement sucks! But until we can run arbitrary
3778 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3780 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3781 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3782 about it and you will realize why. JRR 010720
3783 ****************************************************************************/
3785 static WERROR
save_driver_init_2(NT_PRINTER_INFO_LEVEL
*printer
, uint8
*data
, uint32 data_len
)
3787 WERROR status
= WERR_OK
;
3788 TALLOC_CTX
*ctx
= NULL
;
3789 NT_DEVICEMODE
*nt_devmode
= NULL
;
3790 NT_DEVICEMODE
*tmp_devmode
= printer
->info_2
->devmode
;
3793 * When the DEVMODE is already set on the printer, don't try to unpack it.
3795 DEBUG(8,("save_driver_init_2: Enter...\n"));
3797 if ( !printer
->info_2
->devmode
&& data_len
) {
3799 * Set devmode on printer info, so entire printer initialization can be
3803 if ((ctx
= talloc_init("save_driver_init_2")) == NULL
)
3806 if ((nt_devmode
= (NT_DEVICEMODE
*)malloc(sizeof(NT_DEVICEMODE
))) == NULL
) {
3807 status
= WERR_NOMEM
;
3811 ZERO_STRUCTP(nt_devmode
);
3814 * The DEVMODE is held in the 'data' component of the param in raw binary.
3815 * Convert it to to a devmode structure
3817 if ( !convert_driver_init( ctx
, nt_devmode
, data
, data_len
)) {
3818 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3819 status
= WERR_INVALID_PARAM
;
3823 printer
->info_2
->devmode
= nt_devmode
;
3827 * Pack up and add (or update) the DEVMODE and any current printer data to
3828 * a 'driver init' element in the tdb
3832 if ( update_driver_init(*printer
, 2) != 0 ) {
3833 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3834 status
= WERR_NOMEM
;
3839 * If driver initialization info was successfully saved, set the current
3840 * printer to match it. This allows initialization of the current printer
3841 * as well as the driver.
3843 status
= mod_a_printer(*printer
, 2);
3844 if (!W_ERROR_IS_OK(status
)) {
3845 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3846 printer
->info_2
->printername
));
3850 talloc_destroy(ctx
);
3851 free_nt_devicemode( &nt_devmode
);
3853 printer
->info_2
->devmode
= tmp_devmode
;
3858 /****************************************************************************
3859 Update the driver init info (DEVMODE and specifics) for a printer
3860 ****************************************************************************/
3862 WERROR
save_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
, uint8
*data
, uint32 data_len
)
3864 WERROR status
= WERR_OK
;
3868 status
= save_driver_init_2( printer
, data
, data_len
);
3871 status
= WERR_UNKNOWN_LEVEL
;
3878 /****************************************************************************
3879 Deep copy a NT_PRINTER_DATA
3880 ****************************************************************************/
3882 static NTSTATUS
copy_printer_data( NT_PRINTER_DATA
*dst
, NT_PRINTER_DATA
*src
)
3884 int i
, j
, num_vals
, new_key_index
;
3885 REGVAL_CTR
*src_key
, *dst_key
;
3888 return NT_STATUS_NO_MEMORY
;
3890 for ( i
=0; i
<src
->num_keys
; i
++ ) {
3892 /* create a new instance of the printerkey in the destination
3893 printer_data object */
3895 new_key_index
= add_new_printer_key( dst
, src
->keys
[i
].name
);
3896 dst_key
= &dst
->keys
[new_key_index
].values
;
3898 src_key
= &src
->keys
[i
].values
;
3899 num_vals
= regval_ctr_numvals( src_key
);
3901 /* dup the printer entire printer key */
3903 for ( j
=0; j
<num_vals
; j
++ ) {
3904 regval_ctr_copyvalue( dst_key
, regval_ctr_specific_value(src_key
, j
) );
3908 return NT_STATUS_OK
;
3911 /****************************************************************************
3912 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
3914 ****************************************************************************/
3916 NT_PRINTER_INFO_LEVEL_2
* dup_printer_2( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL_2
*printer
)
3918 NT_PRINTER_INFO_LEVEL_2
*copy
;
3923 if ( !(copy
= (NT_PRINTER_INFO_LEVEL_2
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2
))) )
3926 memcpy( copy
, printer
, sizeof(NT_PRINTER_INFO_LEVEL_2
) );
3928 /* malloc()'d members copied here */
3930 copy
->devmode
= dup_nt_devicemode( printer
->devmode
);
3932 ZERO_STRUCT( copy
->data
);
3933 copy_printer_data( ©
->data
, &printer
->data
);
3935 /* this is talloc()'d; very ugly that we have a structure that
3936 is half malloc()'d and half talloc()'d but that is the way
3937 that the PRINTER_INFO stuff is written right now. --jerry */
3939 copy
->secdesc_buf
= dup_sec_desc_buf( ctx
, printer
->secdesc_buf
);
3944 /****************************************************************************
3945 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3947 Previously the code had a memory allocation problem because it always
3948 used the TALLOC_CTX from the Printer_entry*. This context lasts
3949 as a long as the original handle is open. So if the client made a lot
3950 of getprinter[data]() calls, the memory usage would climb. Now we use
3951 a short lived TALLOC_CTX for printer_info_2 objects returned. We
3952 still use the Printer_entry->ctx for maintaining the cache copy though
3953 since that object must live as long as the handle by definition.
3956 ****************************************************************************/
3958 WERROR
get_a_printer( Printer_entry
*print_hnd
, NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
,
3959 const char *sharename
)
3962 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3966 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename
, (unsigned int)level
));
3970 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
3971 DEBUG(0,("get_a_printer: malloc fail.\n"));
3974 ZERO_STRUCTP(printer
);
3977 * check for cache first. A Printer handle cannot changed
3978 * to another printer object so we only check that the printer
3979 * is actually for a printer and that the printer_info pointer
3983 && (print_hnd
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)
3984 && print_hnd
->printer_info
)
3986 /* get_talloc_ctx() works here because we need a short
3987 lived talloc context */
3989 if ( !(printer
->info_2
= dup_printer_2(get_talloc_ctx(), print_hnd
->printer_info
->info_2
)) )
3991 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
3997 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
3999 *pp_printer
= printer
;
4005 /* no cache for this handle; see if we can match one from another handle.
4006 Make sure to use a short lived talloc ctx */
4009 result
= find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer
->info_2
, sharename
);
4011 /* fail to disk if we don't have it with any open handle */
4013 if ( !print_hnd
|| !W_ERROR_IS_OK(result
) )
4014 result
= get_a_printer_2(&printer
->info_2
, sharename
);
4016 /* we have a new printer now. Save it with this handle */
4018 if ( W_ERROR_IS_OK(result
) ) {
4019 dump_a_printer(*printer
, level
);
4021 /* save a copy in cache */
4022 if ( print_hnd
&& (print_hnd
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)) {
4023 if ( !print_hnd
->printer_info
)
4024 print_hnd
->printer_info
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
));
4026 if ( print_hnd
->printer_info
) {
4027 /* make sure to use the handle's talloc ctx here since
4028 the printer_2 object must last until the handle is closed */
4030 print_hnd
->printer_info
->info_2
= dup_printer_2(print_hnd
->ctx
, printer
->info_2
);
4032 /* don't fail the lookup just because the cache update failed */
4033 if ( !print_hnd
->printer_info
->info_2
)
4034 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4037 *pp_printer
= printer
;
4045 result
=WERR_UNKNOWN_LEVEL
;
4049 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename
, (unsigned int)level
, dos_errstr(result
)));
4054 /****************************************************************************
4055 Deletes a NT_PRINTER_INFO_LEVEL struct.
4056 ****************************************************************************/
4058 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
4061 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
4063 DEBUG(104,("freeing a printer at level [%d]\n", level
));
4065 if (printer
== NULL
)
4070 if (printer
->info_2
!= NULL
) {
4071 free_nt_printer_info_level_2(&printer
->info_2
);
4082 SAFE_FREE(*pp_printer
);
4086 /****************************************************************************
4087 ****************************************************************************/
4088 uint32
add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4091 DEBUG(104,("adding a printer at level [%d]\n", level
));
4092 dump_a_printer_driver(driver
, level
);
4096 result
=add_a_printer_driver_3(driver
.info_3
);
4100 result
=add_a_printer_driver_6(driver
.info_6
);
4110 /****************************************************************************
4111 ****************************************************************************/
4113 WERROR
get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL
*driver
, uint32 level
,
4114 fstring drivername
, const char *architecture
, uint32 version
)
4120 /* Sometime we just want any version of the driver */
4122 if ( version
== DRIVER_ANY_VERSION
) {
4123 /* look for Win2k first and then for NT4 */
4124 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4127 if ( !W_ERROR_IS_OK(result
) ) {
4128 result
= get_a_printer_driver_3( &driver
->info_3
,
4129 drivername
, architecture
, 2 );
4132 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4133 architecture
, version
);
4142 if (W_ERROR_IS_OK(result
))
4143 dump_a_printer_driver(*driver
, level
);
4148 /****************************************************************************
4149 ****************************************************************************/
4150 uint32
free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4157 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
4158 if (driver
.info_3
!= NULL
)
4160 info3
=driver
.info_3
;
4161 SAFE_FREE(info3
->dependentfiles
);
4162 ZERO_STRUCTP(info3
);
4172 NT_PRINTER_DRIVER_INFO_LEVEL_6
*info6
;
4173 if (driver
.info_6
!= NULL
) {
4174 info6
=driver
.info_6
;
4175 SAFE_FREE(info6
->dependentfiles
);
4176 SAFE_FREE(info6
->previousnames
);
4177 ZERO_STRUCTP(info6
);
4193 /****************************************************************************
4194 Determine whether or not a particular driver is currently assigned
4196 ****************************************************************************/
4198 BOOL
printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
)
4201 int n_services
= lp_numservices();
4202 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4207 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4209 /* loop through the printers.tdb and check for the drivername */
4211 for (snum
=0; snum
<n_services
; snum
++) {
4212 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
4215 if ( !W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))) )
4218 if ( !StrCaseCmp(info_3
->name
, printer
->info_2
->drivername
) ) {
4219 free_a_printer( &printer
, 2 );
4223 free_a_printer( &printer
, 2 );
4226 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4228 /* report that the driver is not in use by default */
4234 /**********************************************************************
4235 Check to see if a ogiven file is in use by *info
4236 *********************************************************************/
4238 static BOOL
drv_file_in_use( char* file
, NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4245 if ( strequal(file
, info
->driverpath
) )
4248 if ( strequal(file
, info
->datafile
) )
4251 if ( strequal(file
, info
->configfile
) )
4254 if ( strequal(file
, info
->helpfile
) )
4257 /* see of there are any dependent files to examine */
4259 if ( !info
->dependentfiles
)
4262 while ( *info
->dependentfiles
[i
] ) {
4263 if ( strequal(file
, info
->dependentfiles
[i
]) )
4272 /**********************************************************************
4273 Utility function to remove the dependent file pointed to by the
4274 input parameter from the list
4275 *********************************************************************/
4277 static void trim_dependent_file( fstring files
[], int idx
)
4280 /* bump everything down a slot */
4282 while( *files
[idx
+1] ) {
4283 fstrcpy( files
[idx
], files
[idx
+1] );
4292 /**********************************************************************
4293 Check if any of the files used by src are also used by drv
4294 *********************************************************************/
4296 static BOOL
trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*src
,
4297 NT_PRINTER_DRIVER_INFO_LEVEL_3
*drv
)
4299 BOOL in_use
= False
;
4305 /* check each file. Remove it from the src structure if it overlaps */
4307 if ( drv_file_in_use(src
->driverpath
, drv
) ) {
4309 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driverpath
));
4310 fstrcpy( src
->driverpath
, "" );
4313 if ( drv_file_in_use(src
->datafile
, drv
) ) {
4315 DEBUG(10,("Removing datafile [%s] from list\n", src
->datafile
));
4316 fstrcpy( src
->datafile
, "" );
4319 if ( drv_file_in_use(src
->configfile
, drv
) ) {
4321 DEBUG(10,("Removing configfile [%s] from list\n", src
->configfile
));
4322 fstrcpy( src
->configfile
, "" );
4325 if ( drv_file_in_use(src
->helpfile
, drv
) ) {
4327 DEBUG(10,("Removing helpfile [%s] from list\n", src
->helpfile
));
4328 fstrcpy( src
->helpfile
, "" );
4331 /* are there any dependentfiles to examine? */
4333 if ( !src
->dependentfiles
)
4336 while ( *src
->dependentfiles
[i
] ) {
4337 if ( drv_file_in_use(src
->dependentfiles
[i
], drv
) ) {
4339 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependentfiles
[i
]));
4340 trim_dependent_file( src
->dependentfiles
, i
);
4348 /****************************************************************************
4349 Determine whether or not a particular driver files are currently being
4350 used by any other driver.
4352 Return value is True if any files were in use by other drivers
4353 and False otherwise.
4355 Upon return, *info has been modified to only contain the driver files
4356 which are not in use
4357 ****************************************************************************/
4359 BOOL
printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4364 fstring
*list
= NULL
;
4365 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4370 version
= info
->cversion
;
4372 /* loop over all driver versions */
4374 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4376 /* get the list of drivers */
4379 ndrivers
= get_ntdrivers(&list
, info
->environment
, version
);
4381 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4382 ndrivers
, info
->environment
, version
));
4384 /* check each driver for overlap in files */
4386 for (i
=0; i
<ndrivers
; i
++) {
4387 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
4389 ZERO_STRUCT(driver
);
4391 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, list
[i
], info
->environment
, version
)) ) {
4396 /* check if d2 uses any files from d1 */
4397 /* only if this is a different driver than the one being deleted */
4399 if ( !strequal(info
->name
, driver
.info_3
->name
) ) {
4400 if ( trim_overlap_drv_files(info
, driver
.info_3
) ) {
4401 free_a_printer_driver(driver
, 3);
4407 free_a_printer_driver(driver
, 3);
4412 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4414 driver
.info_3
= info
;
4416 if ( DEBUGLEVEL
>= 20 )
4417 dump_a_printer_driver( driver
, 3 );
4422 /****************************************************************************
4423 Actually delete the driver files. Make sure that
4424 printer_driver_files_in_use() return False before calling
4426 ****************************************************************************/
4428 static BOOL
delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
)
4432 connection_struct
*conn
;
4442 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3
->name
, info_3
->cversion
));
4445 * Connect to the print$ share under the same account as the
4446 * user connected to the rpc pipe. Note we must be root to
4450 null_pw
= data_blob( NULL
, 0 );
4451 fstrcpy(res_type
, "A:");
4453 conn
= make_connection_with_chdir( "print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
4457 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4461 /* Save who we are - we are temporarily becoming the connection user. */
4463 if ( !become_user(conn
, conn
->vuid
) ) {
4464 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4468 /* now delete the files; must strip the '\print$' string from
4471 if ( *info_3
->driverpath
) {
4472 if ( (s
= strchr( &info_3
->driverpath
[1], '\\' )) != NULL
) {
4473 driver_unix_convert(s
, conn
, NULL
, &bad_path
, &st
);
4474 DEBUG(10,("deleting driverfile [%s]\n", s
));
4475 unlink_internals(conn
, 0, s
);
4479 if ( *info_3
->configfile
) {
4480 if ( (s
= strchr( &info_3
->configfile
[1], '\\' )) != NULL
) {
4481 driver_unix_convert(s
, conn
, NULL
, &bad_path
, &st
);
4482 DEBUG(10,("deleting configfile [%s]\n", s
));
4483 unlink_internals(conn
, 0, s
);
4487 if ( *info_3
->datafile
) {
4488 if ( (s
= strchr( &info_3
->datafile
[1], '\\' )) != NULL
) {
4489 driver_unix_convert(s
, conn
, NULL
, &bad_path
, &st
);
4490 DEBUG(10,("deleting datafile [%s]\n", s
));
4491 unlink_internals(conn
, 0, s
);
4495 if ( *info_3
->helpfile
) {
4496 if ( (s
= strchr( &info_3
->helpfile
[1], '\\' )) != NULL
) {
4497 driver_unix_convert(s
, conn
, NULL
, &bad_path
, &st
);
4498 DEBUG(10,("deleting helpfile [%s]\n", s
));
4499 unlink_internals(conn
, 0, s
);
4503 /* check if we are done removing files */
4505 if ( info_3
->dependentfiles
) {
4506 while ( *info_3
->dependentfiles
[i
] ) {
4509 /* bypass the "\print$" portion of the path */
4511 if ( (file
= strchr( info_3
->dependentfiles
[i
]+1, '\\' )) != NULL
) {
4512 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4513 DEBUG(10,("deleting dependent file [%s]\n", file
));
4514 unlink_internals(conn
, 0, file
);
4526 /****************************************************************************
4527 Remove a printer driver from the TDB. This assumes that the the driver was
4528 previously looked up.
4529 ***************************************************************************/
4531 WERROR
delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
,
4532 uint32 version
, BOOL delete_files
)
4536 TDB_DATA kbuf
, dbuf
;
4537 NT_PRINTER_DRIVER_INFO_LEVEL ctr
;
4539 /* delete the tdb data first */
4541 arch
= get_short_archi(info_3
->environment
);
4542 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
,
4543 arch
, version
, info_3
->name
);
4545 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4546 key
, delete_files
? "TRUE" : "FALSE" ));
4548 ctr
.info_3
= info_3
;
4549 dump_a_printer_driver( ctr
, 3 );
4552 kbuf
.dsize
=strlen(key
)+1;
4554 /* check if the driver actually exists for this environment */
4556 dbuf
= tdb_fetch( tdb_drivers
, kbuf
);
4558 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key
));
4559 return WERR_UNKNOWN_PRINTER_DRIVER
;
4562 SAFE_FREE( dbuf
.dptr
);
4564 /* ok... the driver exists so the delete should return success */
4566 if (tdb_delete(tdb_drivers
, kbuf
) == -1) {
4567 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key
));
4568 return WERR_ACCESS_DENIED
;
4572 * now delete any associated files if delete_files == True
4573 * even if this part failes, we return succes because the
4574 * driver doesn not exist any more
4578 delete_driver_files( info_3
, user
);
4581 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key
));
4586 /****************************************************************************
4587 Store a security desc for a printer.
4588 ****************************************************************************/
4590 WERROR
nt_printing_setsec(const char *printername
, SEC_DESC_BUF
*secdesc_ctr
)
4592 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4593 SEC_DESC_BUF
*old_secdesc_ctr
= NULL
;
4595 TALLOC_CTX
*mem_ctx
= NULL
;
4599 mem_ctx
= talloc_init("nt_printing_setsec");
4600 if (mem_ctx
== NULL
)
4603 /* The old owner and group sids of the security descriptor are not
4604 present when new ACEs are added or removed by changing printer
4605 permissions through NT. If they are NULL in the new security
4606 descriptor then copy them over from the old one. */
4608 if (!secdesc_ctr
->sec
->owner_sid
|| !secdesc_ctr
->sec
->grp_sid
) {
4609 DOM_SID
*owner_sid
, *group_sid
;
4610 SEC_ACL
*dacl
, *sacl
;
4611 SEC_DESC
*psd
= NULL
;
4614 nt_printing_getsec(mem_ctx
, printername
, &old_secdesc_ctr
);
4616 /* Pick out correct owner and group sids */
4618 owner_sid
= secdesc_ctr
->sec
->owner_sid
?
4619 secdesc_ctr
->sec
->owner_sid
:
4620 old_secdesc_ctr
->sec
->owner_sid
;
4622 group_sid
= secdesc_ctr
->sec
->grp_sid
?
4623 secdesc_ctr
->sec
->grp_sid
:
4624 old_secdesc_ctr
->sec
->grp_sid
;
4626 dacl
= secdesc_ctr
->sec
->dacl
?
4627 secdesc_ctr
->sec
->dacl
:
4628 old_secdesc_ctr
->sec
->dacl
;
4630 sacl
= secdesc_ctr
->sec
->sacl
?
4631 secdesc_ctr
->sec
->sacl
:
4632 old_secdesc_ctr
->sec
->sacl
;
4634 /* Make a deep copy of the security descriptor */
4636 psd
= make_sec_desc(mem_ctx
, secdesc_ctr
->sec
->revision
, secdesc_ctr
->sec
->type
,
4637 owner_sid
, group_sid
,
4642 new_secdesc_ctr
= make_sec_desc_buf(mem_ctx
, size
, psd
);
4645 if (!new_secdesc_ctr
) {
4646 new_secdesc_ctr
= secdesc_ctr
;
4649 /* Store the security descriptor in a tdb */
4651 prs_init(&ps
, (uint32
)sec_desc_size(new_secdesc_ctr
->sec
) +
4652 sizeof(SEC_DESC_BUF
), mem_ctx
, MARSHALL
);
4654 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr
,
4656 status
= WERR_BADFUNC
;
4660 slprintf(key
, sizeof(key
)-1, "SECDESC/%s", printername
);
4662 if (tdb_prs_store(tdb_printers
, key
, &ps
)==0) {
4665 DEBUG(1,("Failed to store secdesc for %s\n", printername
));
4666 status
= WERR_BADFUNC
;
4669 /* Free malloc'ed memory */
4675 talloc_destroy(mem_ctx
);
4679 /****************************************************************************
4680 Construct a default security descriptor buffer for a printer.
4681 ****************************************************************************/
4683 static SEC_DESC_BUF
*construct_default_printer_sdb(TALLOC_CTX
*ctx
)
4687 SEC_ACL
*psa
= NULL
;
4688 SEC_DESC_BUF
*sdb
= NULL
;
4689 SEC_DESC
*psd
= NULL
;
4693 /* Create an ACE where Everyone is allowed to print */
4695 init_sec_access(&sa
, PRINTER_ACE_PRINT
);
4696 init_sec_ace(&ace
[0], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4697 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4699 /* Make the security descriptor owned by the Administrators group
4700 on the PDC of the domain. */
4702 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
4703 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4706 /* Backup plan - make printer owned by admins.
4707 This should emulate a lanman printer as security
4708 settings can't be changed. */
4710 sid_copy(&owner_sid
, get_global_sam_sid());
4711 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4714 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
4715 init_sec_ace(&ace
[1], &owner_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4716 sa
, SEC_ACE_FLAG_OBJECT_INHERIT
|
4717 SEC_ACE_FLAG_INHERIT_ONLY
);
4719 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
4720 init_sec_ace(&ace
[2], &owner_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4721 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4723 /* The ACL revision number in rpc_secdesc.h differs from the one
4724 created by NT when setting ACE entries in printer
4725 descriptors. NT4 complains about the property being edited by a
4728 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, 3, ace
)) != NULL
) {
4729 psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
4731 NULL
, psa
, &sd_size
);
4735 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4739 sdb
= make_sec_desc_buf(ctx
, sd_size
, psd
);
4741 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4742 (unsigned int)sd_size
));
4747 /****************************************************************************
4748 Get a security desc for a printer.
4749 ****************************************************************************/
4751 BOOL
nt_printing_getsec(TALLOC_CTX
*ctx
, const char *printername
, SEC_DESC_BUF
**secdesc_ctr
)
4757 if (strlen(printername
) > 2 && (temp
= strchr(printername
+ 2, '\\'))) {
4758 printername
= temp
+ 1;
4761 /* Fetch security descriptor from tdb */
4763 slprintf(key
, sizeof(key
)-1, "SECDESC/%s", printername
);
4765 if (tdb_prs_fetch(tdb_printers
, key
, &ps
, ctx
)!=0 ||
4766 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1)) {
4768 DEBUG(4,("using default secdesc for %s\n", printername
));
4770 if (!(*secdesc_ctr
= construct_default_printer_sdb(ctx
))) {
4774 /* Save default security descriptor for later */
4776 prs_init(&ps
, (uint32
)sec_desc_size((*secdesc_ctr
)->sec
) +
4777 sizeof(SEC_DESC_BUF
), ctx
, MARSHALL
);
4779 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1))
4780 tdb_prs_store(tdb_printers
, key
, &ps
);
4787 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4788 this security descriptor has been created when winbindd was
4789 down. Take ownership of security descriptor. */
4791 if (sid_equal((*secdesc_ctr
)->sec
->owner_sid
, &global_sid_World
)) {
4794 /* Change sd owner to workgroup administrator */
4796 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
4797 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4798 SEC_DESC
*psd
= NULL
;
4803 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4805 psd
= make_sec_desc(ctx
, (*secdesc_ctr
)->sec
->revision
, (*secdesc_ctr
)->sec
->type
,
4807 (*secdesc_ctr
)->sec
->grp_sid
,
4808 (*secdesc_ctr
)->sec
->sacl
,
4809 (*secdesc_ctr
)->sec
->dacl
,
4812 new_secdesc_ctr
= make_sec_desc_buf(ctx
, size
, psd
);
4814 /* Swap with other one */
4816 *secdesc_ctr
= new_secdesc_ctr
;
4820 nt_printing_setsec(printername
, *secdesc_ctr
);
4824 if (DEBUGLEVEL
>= 10) {
4825 SEC_ACL
*the_acl
= (*secdesc_ctr
)->sec
->dacl
;
4828 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4829 printername
, the_acl
->num_aces
));
4831 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4834 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
4836 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str
,
4837 the_acl
->ace
[i
].type
, the_acl
->ace
[i
].flags
,
4838 the_acl
->ace
[i
].info
.mask
));
4848 1: level not implemented
4849 2: file doesn't exist
4850 3: can't allocate memory
4851 4: can't free memory
4852 5: non existant struct
4856 A printer and a printer driver are 2 different things.
4857 NT manages them separatelly, Samba does the same.
4858 Why ? Simply because it's easier and it makes sense !
4860 Now explanation: You have 3 printers behind your samba server,
4861 2 of them are the same make and model (laser A and B). But laser B
4862 has an 3000 sheet feeder and laser A doesn't such an option.
4863 Your third printer is an old dot-matrix model for the accounting :-).
4865 If the /usr/local/samba/lib directory (default dir), you will have
4866 5 files to describe all of this.
4868 3 files for the printers (1 by printer):
4871 NTprinter_accounting
4872 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4873 NTdriver_printer model X
4874 NTdriver_printer model Y
4876 jfm: I should use this comment for the text file to explain
4877 same thing for the forms BTW.
4878 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4882 /* Convert generic access rights to printer object specific access rights.
4883 It turns out that NT4 security descriptors use generic access rights and
4884 NT5 the object specific ones. */
4886 void map_printer_permissions(SEC_DESC
*sd
)
4890 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
4891 se_map_generic(&sd
->dacl
->ace
[i
].info
.mask
,
4892 &printer_generic_mapping
);
4896 /****************************************************************************
4897 Check a user has permissions to perform the given operation. We use the
4898 permission constants defined in include/rpc_spoolss.h to check the various
4899 actions we perform when checking printer access.
4901 PRINTER_ACCESS_ADMINISTER:
4902 print_queue_pause, print_queue_resume, update_printer_sec,
4903 update_printer, spoolss_addprinterex_level_2,
4904 _spoolss_setprinterdata
4909 JOB_ACCESS_ADMINISTER:
4910 print_job_delete, print_job_pause, print_job_resume,
4913 ****************************************************************************/
4914 BOOL
print_access_check(struct current_user
*user
, int snum
, int access_type
)
4916 SEC_DESC_BUF
*secdesc
= NULL
;
4917 uint32 access_granted
;
4921 TALLOC_CTX
*mem_ctx
= NULL
;
4922 extern struct current_user current_user
;
4924 /* If user is NULL then use the current_user structure */
4927 user
= ¤t_user
;
4929 /* Always allow root or printer admins to do anything */
4931 if (user
->uid
== 0 ||
4932 user_in_list(uidtoname(user
->uid
), lp_printer_admin(snum
), user
->groups
, user
->ngroups
)) {
4936 /* Get printer name */
4938 pname
= PRINTERNAME(snum
);
4940 if (!pname
|| !*pname
) {
4945 /* Get printer security descriptor */
4947 if(!(mem_ctx
= talloc_init("print_access_check"))) {
4952 nt_printing_getsec(mem_ctx
, pname
, &secdesc
);
4954 if (access_type
== JOB_ACCESS_ADMINISTER
) {
4955 SEC_DESC_BUF
*parent_secdesc
= secdesc
;
4957 /* Create a child security descriptor to check permissions
4958 against. This is because print jobs are child objects
4959 objects of a printer. */
4961 secdesc
= se_create_child_secdesc(mem_ctx
, parent_secdesc
->sec
, False
);
4963 /* Now this is the bit that really confuses me. The access
4964 type needs to be changed from JOB_ACCESS_ADMINISTER to
4965 PRINTER_ACCESS_ADMINISTER for this to work. Something
4966 to do with the child (job) object becoming like a
4969 access_type
= PRINTER_ACCESS_ADMINISTER
;
4974 map_printer_permissions(secdesc
->sec
);
4976 result
= se_access_check(secdesc
->sec
, user
->nt_user_token
, access_type
,
4977 &access_granted
, &status
);
4979 DEBUG(4, ("access check was %s\n", result
? "SUCCESS" : "FAILURE"));
4981 talloc_destroy(mem_ctx
);
4989 /****************************************************************************
4990 Check the time parameters allow a print operation.
4991 *****************************************************************************/
4993 BOOL
print_time_access_check(int snum
)
4995 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4997 time_t now
= time(NULL
);
5001 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))))
5004 if (printer
->info_2
->starttime
== 0 && printer
->info_2
->untiltime
== 0)
5008 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
5010 if (mins
>= printer
->info_2
->starttime
&& mins
<= printer
->info_2
->untiltime
)
5013 free_a_printer(&printer
, 2);