2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
6 * Copyright (C) Gerald Carter 2002-2003.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 extern DOM_SID global_sid_World
;
27 static TDB_CONTEXT
*tdb_forms
; /* used for forms files */
28 static TDB_CONTEXT
*tdb_drivers
; /* used for driver files */
29 static TDB_CONTEXT
*tdb_printers
; /* used for printers files */
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
42 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
44 /* Map generic permissions to printer object specific permissions */
46 GENERIC_MAPPING printer_generic_mapping
= {
53 STANDARD_MAPPING printer_std_mapping
= {
60 /* Map generic permissions to print server object specific permissions */
62 GENERIC_MAPPING printserver_generic_mapping
= {
69 STANDARD_MAPPING printserver_std_mapping
= {
76 /* We need one default form to support our default printer. Msoft adds the
77 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
78 array index). Letter is always first, so (for the current code) additions
79 always put things in the correct order. */
80 static const nt_forms_struct default_forms
[] = {
81 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
84 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
85 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
86 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
87 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
88 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
89 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
92 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
93 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
94 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
95 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
96 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
97 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
98 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
99 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
100 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
101 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
102 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
103 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
104 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
105 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
106 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
107 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
108 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
109 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
110 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
111 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
112 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
113 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
114 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
115 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
116 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
117 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
118 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
119 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
120 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
121 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
122 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
123 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
124 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
125 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
126 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
127 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
128 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
131 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
132 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
133 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
134 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
135 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
136 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
138 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
139 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
140 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
141 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
142 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
143 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
144 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
145 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
146 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
147 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
148 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
149 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
150 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
151 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
152 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
153 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
154 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
155 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
156 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
157 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
158 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
159 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
160 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
161 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
162 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
163 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
164 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
165 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
166 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
167 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
168 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
169 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
170 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
171 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
172 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
173 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
174 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
175 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
176 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
177 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
178 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
179 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
180 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
181 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
182 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
183 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
184 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
185 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
186 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
187 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
188 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
189 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
190 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
191 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
192 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
193 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
194 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
195 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
196 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
197 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
198 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
202 const char *long_archi
;
203 const char *short_archi
;
207 #define SPL_ARCH_WIN40 "WIN40"
208 #define SPL_ARCH_W32X86 "W32X86"
209 #define SPL_ARCH_W32MIPS "W32MIPS"
210 #define SPL_ARCH_W32ALPHA "W32ALPHA"
211 #define SPL_ARCH_W32PPC "W32PPC"
213 static const struct table_node archi_table
[]= {
215 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
216 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
217 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
218 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
219 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
223 static BOOL
upgrade_to_version_3(void)
225 TDB_DATA kbuf
, newkey
, dbuf
;
227 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
229 for (kbuf
= tdb_firstkey(tdb_drivers
); kbuf
.dptr
;
230 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
232 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
234 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) == 0) {
235 DEBUG(0,("upgrade_to_version_3:moving form\n"));
236 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
237 SAFE_FREE(dbuf
.dptr
);
238 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms
)));
241 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
242 SAFE_FREE(dbuf
.dptr
);
243 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
248 if (strncmp(kbuf
.dptr
, PRINTERS_PREFIX
, strlen(PRINTERS_PREFIX
)) == 0) {
249 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
250 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
251 SAFE_FREE(dbuf
.dptr
);
252 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers
)));
255 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
256 SAFE_FREE(dbuf
.dptr
);
257 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
262 if (strncmp(kbuf
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
)) == 0) {
263 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
264 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
265 SAFE_FREE(dbuf
.dptr
);
266 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers
)));
269 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
270 SAFE_FREE(dbuf
.dptr
);
271 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
276 SAFE_FREE(dbuf
.dptr
);
282 /****************************************************************************
283 Open the NT printing tdbs. Done once before fork().
284 ****************************************************************************/
286 BOOL
nt_printing_init(void)
288 static pid_t local_pid
;
289 const char *vstring
= "INFO/version";
291 if (tdb_drivers
&& tdb_printers
&& tdb_forms
&& local_pid
== sys_getpid())
295 tdb_close(tdb_drivers
);
296 tdb_drivers
= tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
298 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
299 lock_path("ntdrivers.tdb"), strerror(errno
) ));
304 tdb_close(tdb_printers
);
305 tdb_printers
= tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
307 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
308 lock_path("ntprinters.tdb"), strerror(errno
) ));
313 tdb_close(tdb_forms
);
314 tdb_forms
= tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
316 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
317 lock_path("ntforms.tdb"), strerror(errno
) ));
321 local_pid
= sys_getpid();
323 /* handle a Samba upgrade */
324 tdb_lock_bystring(tdb_drivers
, vstring
, 0);
328 /* Cope with byte-reversed older versions of the db. */
329 vers_id
= tdb_fetch_int32(tdb_drivers
, vstring
);
330 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_2
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_2
)) {
331 /* Written on a bigendian machine with old fetch_int code. Save as le. */
332 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
333 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION
);
334 vers_id
= NTDRIVERS_DATABASE_VERSION
;
337 if (vers_id
!= NTDRIVERS_DATABASE_VERSION
) {
339 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_1
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_1
)) {
340 if (!upgrade_to_version_3())
343 tdb_traverse(tdb_drivers
, tdb_traverse_delete_fn
, NULL
);
345 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION
);
348 tdb_unlock_bystring(tdb_drivers
, vstring
);
350 update_c_setprinter(True
);
353 * register callback to handle updating printers as new
354 * drivers are installed
357 message_register( MSG_PRINTER_DRVUPGRADE
, do_drv_upgrade_printer
);
360 * register callback to handle updating printer data
361 * when a driver is initialized
364 message_register( MSG_PRINTERDATA_INIT_RESET
, reset_all_printerdata
);
370 /*******************************************************************
371 tdb traversal function for counting printers.
372 ********************************************************************/
374 static int traverse_counting_printers(TDB_CONTEXT
*t
, TDB_DATA key
,
375 TDB_DATA data
, void *context
)
377 int *printer_count
= (int*)context
;
379 if (memcmp(PRINTERS_PREFIX
, key
.dptr
, sizeof(PRINTERS_PREFIX
)-1) == 0) {
381 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key
.dptr
, *printer_count
));
387 /*******************************************************************
388 Update the spooler global c_setprinter. This variable is initialized
389 when the parent smbd starts with the number of existing printers. It
390 is monotonically increased by the current number of printers *after*
391 each add or delete printer RPC. Only Microsoft knows why... JRR020119
392 ********************************************************************/
394 uint32
update_c_setprinter(BOOL initialize
)
397 int32 printer_count
= 0;
399 tdb_lock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
, 0);
401 /* Traverse the tdb, counting the printers */
402 tdb_traverse(tdb_printers
, traverse_counting_printers
, (void *)&printer_count
);
404 /* If initializing, set c_setprinter to current printers count
405 * otherwise, bump it by the current printer count
408 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
) + printer_count
;
410 c_setprinter
= printer_count
;
412 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter
));
413 tdb_store_int32(tdb_printers
, GLOBAL_C_SETPRINTER
, c_setprinter
);
415 tdb_unlock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
417 return (uint32
)c_setprinter
;
420 /*******************************************************************
421 Get the spooler global c_setprinter, accounting for initialization.
422 ********************************************************************/
424 uint32
get_c_setprinter(void)
426 int32 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
);
428 if (c_setprinter
== (int32
)-1)
429 c_setprinter
= update_c_setprinter(True
);
431 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter
));
433 return (uint32
)c_setprinter
;
436 /****************************************************************************
437 Get builtin form struct list.
438 ****************************************************************************/
440 int get_builtin_ntforms(nt_forms_struct
**list
)
442 *list
= (nt_forms_struct
*)memdup(&default_forms
[0], sizeof(default_forms
));
443 return sizeof(default_forms
) / sizeof(default_forms
[0]);
446 /****************************************************************************
447 get a builtin form struct
448 ****************************************************************************/
450 BOOL
get_a_builtin_ntform(UNISTR2
*uni_formname
,nt_forms_struct
*form
)
454 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
455 DEBUGADD(6,("Looking for builtin form %s \n", form_name
));
456 count
= sizeof(default_forms
) / sizeof(default_forms
[0]);
457 for (i
=0;i
<count
;i
++) {
458 if (strequal(form_name
,default_forms
[i
].name
)) {
459 DEBUGADD(6,("Found builtin form %s \n", form_name
));
460 memcpy(form
,&default_forms
[i
],sizeof(*form
));
468 /****************************************************************************
469 get a form struct list
470 ****************************************************************************/
471 int get_ntforms(nt_forms_struct
**list
)
473 TDB_DATA kbuf
, newkey
, dbuf
;
475 nt_forms_struct form
;
480 for (kbuf
= tdb_firstkey(tdb_forms
);
482 newkey
= tdb_nextkey(tdb_forms
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
)
484 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) != 0)
487 dbuf
= tdb_fetch(tdb_forms
, kbuf
);
491 fstrcpy(form
.name
, kbuf
.dptr
+strlen(FORMS_PREFIX
));
492 ret
= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dddddddd",
493 &i
, &form
.flag
, &form
.width
, &form
.length
, &form
.left
,
494 &form
.top
, &form
.right
, &form
.bottom
);
495 SAFE_FREE(dbuf
.dptr
);
496 if (ret
!= dbuf
.dsize
)
499 tl
= Realloc(*list
, sizeof(nt_forms_struct
)*(n
+1));
501 DEBUG(0,("get_ntforms: Realloc fail.\n"));
513 /****************************************************************************
514 write a form struct list
515 ****************************************************************************/
516 int write_ntforms(nt_forms_struct
**list
, int number
)
523 for (i
=0;i
<number
;i
++) {
524 /* save index, so list is rebuilt in correct order */
525 len
= tdb_pack(buf
, sizeof(buf
), "dddddddd",
526 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
527 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
529 if (len
> sizeof(buf
)) break;
530 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[i
].name
);
531 kbuf
.dsize
= strlen(key
)+1;
535 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) break;
541 /****************************************************************************
542 add a form struct at the end of the list
543 ****************************************************************************/
544 BOOL
add_a_form(nt_forms_struct
**list
, const FORM
*form
, int *count
)
552 * NT tries to add forms even when
553 * they are already in the base
554 * only update the values if already present
559 unistr2_to_ascii(form_name
, &form
->name
, sizeof(form_name
)-1);
560 for (n
=0; n
<*count
; n
++) {
561 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
562 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name
));
569 if((tl
=Realloc(*list
, (n
+1)*sizeof(nt_forms_struct
))) == NULL
) {
570 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
574 unistr2_to_ascii((*list
)[n
].name
, &form
->name
, sizeof((*list
)[n
].name
)-1);
578 (*list
)[n
].flag
=form
->flags
;
579 (*list
)[n
].width
=form
->size_x
;
580 (*list
)[n
].length
=form
->size_y
;
581 (*list
)[n
].left
=form
->left
;
582 (*list
)[n
].top
=form
->top
;
583 (*list
)[n
].right
=form
->right
;
584 (*list
)[n
].bottom
=form
->bottom
;
589 /****************************************************************************
590 Delete a named form struct.
591 ****************************************************************************/
593 BOOL
delete_a_form(nt_forms_struct
**list
, UNISTR2
*del_name
, int *count
, WERROR
*ret
)
602 unistr2_to_ascii(form_name
, del_name
, sizeof(form_name
)-1);
604 for (n
=0; n
<*count
; n
++) {
605 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
606 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name
));
612 DEBUG(10,("delete_a_form, [%s] not found\n", form_name
));
613 *ret
= WERR_INVALID_PARAM
;
617 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[n
].name
);
618 kbuf
.dsize
= strlen(key
)+1;
620 if (tdb_delete(tdb_forms
, kbuf
) != 0) {
628 /****************************************************************************
629 Update a form struct.
630 ****************************************************************************/
632 void update_a_form(nt_forms_struct
**list
, const FORM
*form
, int count
)
636 unistr2_to_ascii(form_name
, &(form
->name
), sizeof(form_name
)-1);
638 DEBUG(106, ("[%s]\n", form_name
));
639 for (n
=0; n
<count
; n
++) {
640 DEBUGADD(106, ("n [%d]:[%s]\n", n
, (*list
)[n
].name
));
641 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
)))
645 if (n
==count
) return;
647 (*list
)[n
].flag
=form
->flags
;
648 (*list
)[n
].width
=form
->size_x
;
649 (*list
)[n
].length
=form
->size_y
;
650 (*list
)[n
].left
=form
->left
;
651 (*list
)[n
].top
=form
->top
;
652 (*list
)[n
].right
=form
->right
;
653 (*list
)[n
].bottom
=form
->bottom
;
656 /****************************************************************************
657 Get the nt drivers list.
658 Traverse the database and look-up the matching names.
659 ****************************************************************************/
660 int get_ntdrivers(fstring
**list
, const char *architecture
, uint32 version
)
663 const char *short_archi
;
666 TDB_DATA kbuf
, newkey
;
668 short_archi
= get_short_archi(architecture
);
669 slprintf(key
, sizeof(key
)-1, "%s%s/%d/", DRIVERS_PREFIX
, short_archi
, version
);
671 for (kbuf
= tdb_firstkey(tdb_drivers
);
673 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
675 if (strncmp(kbuf
.dptr
, key
, strlen(key
)) != 0)
678 if((fl
= Realloc(*list
, sizeof(fstring
)*(total
+1))) == NULL
) {
679 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
684 fstrcpy((*list
)[total
], kbuf
.dptr
+strlen(key
));
691 /****************************************************************************
692 function to do the mapping between the long architecture name and
694 ****************************************************************************/
695 const char *get_short_archi(const char *long_archi
)
699 DEBUG(107,("Getting architecture dependant directory\n"));
702 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
703 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
705 if (archi_table
[i
].long_archi
==NULL
) {
706 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
710 /* this might be client code - but shouldn't this be an fstrcpy etc? */
713 DEBUGADD(108,("index: [%d]\n", i
));
714 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
715 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
717 return archi_table
[i
].short_archi
;
720 /****************************************************************************
721 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
722 There are two case to be covered here: PE (Portable Executable) and NE (New
723 Executable) files. Both files support the same INFO structure, but PE files
724 store the signature in unicode, and NE files store it as !unicode.
725 returns -1 on error, 1 on version info found, and 0 on no version info found.
726 ****************************************************************************/
728 static int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
734 if ((buf
=malloc(PE_HEADER_SIZE
)) == NULL
) {
735 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
736 fname
, PE_HEADER_SIZE
));
740 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
741 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
742 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
743 fname
, (unsigned long)byte_count
));
744 goto no_version_info
;
747 /* Is this really a DOS header? */
748 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
749 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
750 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
751 goto no_version_info
;
754 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
755 if (SMB_VFS_LSEEK(fsp
, fsp
->fd
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
756 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
758 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
759 goto no_version_info
;
762 if ((byte_count
= vfs_read_data(fsp
, buf
, PE_HEADER_SIZE
)) < PE_HEADER_SIZE
) {
763 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
764 fname
, (unsigned long)byte_count
));
765 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
766 goto no_version_info
;
769 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
770 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
771 unsigned int num_sections
;
772 unsigned int section_table_bytes
;
774 if (SVAL(buf
,PE_HEADER_MACHINE_OFFSET
) != PE_HEADER_MACHINE_I386
) {
775 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
776 fname
, SVAL(buf
,PE_HEADER_MACHINE_OFFSET
)));
777 /* At this point, we assume the file is in error. It still could be somthing
778 * else besides a PE file, but it unlikely at this point.
783 /* get the section table */
784 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
785 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
786 if (section_table_bytes
== 0)
790 if ((buf
=malloc(section_table_bytes
)) == NULL
) {
791 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
792 fname
, section_table_bytes
));
796 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
797 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
798 fname
, (unsigned long)byte_count
));
802 /* Iterate the section table looking for the resource section ".rsrc" */
803 for (i
= 0; i
< num_sections
; i
++) {
804 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
806 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
807 unsigned int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
808 unsigned int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
810 if (section_bytes
== 0)
814 if ((buf
=malloc(section_bytes
)) == NULL
) {
815 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
816 fname
, section_bytes
));
820 /* Seek to the start of the .rsrc section info */
821 if (SMB_VFS_LSEEK(fsp
, fsp
->fd
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
822 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
827 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
828 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
829 fname
, (unsigned long)byte_count
));
833 if (section_bytes
< VS_VERSION_INFO_UNICODE_SIZE
)
836 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
837 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
838 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
839 /* Align to next long address */
840 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
842 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
843 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
844 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
846 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
847 fname
, *major
, *minor
,
848 (*major
>>16)&0xffff, *major
&0xffff,
849 (*minor
>>16)&0xffff, *minor
&0xffff));
858 /* Version info not found, fall back to origin date/time */
859 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
863 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
864 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
865 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
866 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
867 /* At this point, we assume the file is in error. It still could be somthing
868 * else besides a NE file, but it unlikely at this point. */
872 /* Allocate a bit more space to speed up things */
874 if ((buf
=malloc(VS_NE_BUF_SIZE
)) == NULL
) {
875 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
876 fname
, PE_HEADER_SIZE
));
880 /* This is a HACK! I got tired of trying to sort through the messy
881 * 'NE' file format. If anyone wants to clean this up please have at
882 * it, but this works. 'NE' files will eventually fade away. JRR */
883 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
884 /* Cover case that should not occur in a well formed 'NE' .dll file */
885 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
887 for(i
=0; i
<byte_count
; i
++) {
888 /* Fast skip past data that can't possibly match */
889 if (buf
[i
] != 'V') continue;
891 /* Potential match data crosses buf boundry, move it to beginning
892 * of buf, and fill the buf with as much as it will hold. */
893 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
896 memcpy(buf
, &buf
[i
], byte_count
-i
);
897 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
898 (byte_count
-i
))) < 0) {
900 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
905 byte_count
= bc
+ (byte_count
- i
);
906 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
911 /* Check that the full signature string and the magic number that
912 * follows exist (not a perfect solution, but the chances that this
913 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
914 * twice, as it is simpler to read the code. */
915 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
916 /* Compute skip alignment to next long address */
917 int skip
= -(SMB_VFS_LSEEK(fsp
, fsp
->fd
, 0, SEEK_CUR
) - (byte_count
- i
) +
918 sizeof(VS_SIGNATURE
)) & 3;
919 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
921 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
922 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
923 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
924 fname
, *major
, *minor
,
925 (*major
>>16)&0xffff, *major
&0xffff,
926 (*minor
>>16)&0xffff, *minor
&0xffff));
933 /* Version info not found, fall back to origin date/time */
934 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
939 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
940 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
941 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
952 /****************************************************************************
953 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
954 share one or more files. During the MS installation process files are checked
955 to insure that only a newer version of a shared file is installed over an
956 older version. There are several possibilities for this comparison. If there
957 is no previous version, the new one is newer (obviously). If either file is
958 missing the version info structure, compare the creation date (on Unix use
959 the modification date). Otherwise chose the numerically larger version number.
960 ****************************************************************************/
962 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
964 BOOL use_version
= True
;
969 time_t new_create_time
;
973 time_t old_create_time
;
977 files_struct
*fsp
= NULL
;
979 SMB_STRUCT_STAT stat_buf
;
983 ZERO_STRUCT(stat_buf
);
984 new_create_time
= (time_t)0;
985 old_create_time
= (time_t)0;
987 /* Get file version info (if available) for previous file (if it exists) */
988 pstrcpy(filepath
, old_file
);
990 unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
992 fsp
= open_file_shared(conn
, filepath
, &stat_buf
,
993 SET_OPEN_MODE(DOS_OPEN_RDONLY
),
994 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
995 0, 0, &access_mode
, &action
);
997 /* Old file not found, so by definition new file is in fact newer */
998 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1003 int ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
1004 if (ret
== -1) goto error_exit
;
1007 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1009 use_version
= False
;
1010 if (SMB_VFS_FSTAT(fsp
, fsp
->fd
, &st
) == -1) goto error_exit
;
1011 old_create_time
= st
.st_mtime
;
1012 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time
));
1015 close_file(fsp
, True
);
1017 /* Get file version info (if available) for new file */
1018 pstrcpy(filepath
, new_file
);
1019 unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1021 fsp
= open_file_shared(conn
, filepath
, &stat_buf
,
1022 SET_OPEN_MODE(DOS_OPEN_RDONLY
),
1023 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1024 0, 0, &access_mode
, &action
);
1026 /* New file not found, this shouldn't occur if the caller did its job */
1027 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1032 int ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
1033 if (ret
== -1) goto error_exit
;
1036 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1038 use_version
= False
;
1039 if (SMB_VFS_FSTAT(fsp
, fsp
->fd
, &st
) == -1) goto error_exit
;
1040 new_create_time
= st
.st_mtime
;
1041 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time
));
1044 close_file(fsp
, True
);
1046 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
1047 /* Compare versions and choose the larger version number */
1048 if (new_major
> old_major
||
1049 (new_major
== old_major
&& new_minor
> old_minor
)) {
1051 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1055 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1060 /* Compare modification time/dates and choose the newest time/date */
1061 if (new_create_time
> old_create_time
) {
1062 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1066 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1073 close_file(fsp
, True
);
1077 /****************************************************************************
1078 Determine the correct cVersion associated with an architecture and driver
1079 ****************************************************************************/
1080 static uint32
get_correct_cversion(const char *architecture
, fstring driverpath_in
,
1081 struct current_user
*user
, WERROR
*perr
)
1090 files_struct
*fsp
= NULL
;
1093 connection_struct
*conn
;
1097 *perr
= WERR_INVALID_PARAM
;
1099 /* If architecture is Windows 95/98/ME, the version is always 0. */
1100 if (strcmp(architecture
, "WIN40") == 0) {
1101 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1107 * Connect to the print$ share under the same account as the user connected
1108 * to the rpc pipe. Note we must still be root to do this.
1111 /* Null password is ok - we are already an authenticated user... */
1112 null_pw
= data_blob(NULL
, 0);
1113 fstrcpy(res_type
, "A:");
1115 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1119 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1120 *perr
= ntstatus_to_werror(nt_status
);
1124 /* We are temporarily becoming the connection user. */
1125 if (!become_user(conn
, user
->vuid
)) {
1126 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1127 *perr
= WERR_ACCESS_DENIED
;
1131 /* Open the driver file (Portable Executable format) and determine the
1132 * deriver the cversion. */
1133 slprintf(driverpath
, sizeof(driverpath
)-1, "%s/%s", architecture
, driverpath_in
);
1135 unix_convert(driverpath
,conn
,NULL
,&bad_path
,&st
);
1137 fsp
= open_file_shared(conn
, driverpath
, &st
,
1138 SET_OPEN_MODE(DOS_OPEN_RDONLY
),
1139 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1140 0, 0, &access_mode
, &action
);
1142 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1143 driverpath
, errno
));
1144 *perr
= WERR_ACCESS_DENIED
;
1150 int ret
= get_file_version(fsp
, driverpath
, &major
, &minor
);
1151 if (ret
== -1) goto error_exit
;
1154 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath
));
1159 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1160 * for more details. Version in this case is not just the version of the
1161 * file, but the version in the sense of kernal mode (2) vs. user mode
1162 * (3) drivers. Other bits of the version fields are the version info.
1165 cversion
= major
& 0x0000ffff;
1167 case 2: /* WinNT drivers */
1168 case 3: /* Win2K drivers */
1172 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1173 driverpath
, cversion
));
1177 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1178 driverpath
, major
, minor
));
1181 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1182 driverpath
, cversion
));
1184 close_file(fsp
, True
);
1185 close_cnum(conn
, user
->vuid
);
1194 close_file(fsp
, True
);
1196 close_cnum(conn
, user
->vuid
);
1201 /****************************************************************************
1202 ****************************************************************************/
1203 static WERROR
clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
,
1204 struct current_user
*user
)
1206 const char *architecture
;
1212 /* clean up the driver name.
1213 * we can get .\driver.dll
1214 * or worse c:\windows\system\driver.dll !
1216 /* using an intermediate string to not have overlaping memcpy()'s */
1217 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1218 fstrcpy(new_name
, p
+1);
1219 fstrcpy(driver
->driverpath
, new_name
);
1222 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1223 fstrcpy(new_name
, p
+1);
1224 fstrcpy(driver
->datafile
, new_name
);
1227 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1228 fstrcpy(new_name
, p
+1);
1229 fstrcpy(driver
->configfile
, new_name
);
1232 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1233 fstrcpy(new_name
, p
+1);
1234 fstrcpy(driver
->helpfile
, new_name
);
1237 if (driver
->dependentfiles
) {
1238 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1239 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1240 fstrcpy(new_name
, p
+1);
1241 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1246 architecture
= get_short_archi(driver
->environment
);
1248 /* jfm:7/16/2000 the client always sends the cversion=0.
1249 * The server should check which version the driver is by reading
1250 * the PE header of driver->driverpath.
1252 * For Windows 95/98 the version is 0 (so the value sent is correct)
1253 * For Windows NT (the architecture doesn't matter)
1254 * NT 3.1: cversion=0
1255 * NT 3.5/3.51: cversion=1
1259 if ((driver
->cversion
= get_correct_cversion( architecture
,
1260 driver
->driverpath
, user
, &err
)) == -1)
1266 /****************************************************************************
1267 ****************************************************************************/
1268 static WERROR
clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
, struct current_user
*user
)
1270 const char *architecture
;
1276 /* clean up the driver name.
1277 * we can get .\driver.dll
1278 * or worse c:\windows\system\driver.dll !
1280 /* using an intermediate string to not have overlaping memcpy()'s */
1281 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1282 fstrcpy(new_name
, p
+1);
1283 fstrcpy(driver
->driverpath
, new_name
);
1286 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1287 fstrcpy(new_name
, p
+1);
1288 fstrcpy(driver
->datafile
, new_name
);
1291 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1292 fstrcpy(new_name
, p
+1);
1293 fstrcpy(driver
->configfile
, new_name
);
1296 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1297 fstrcpy(new_name
, p
+1);
1298 fstrcpy(driver
->helpfile
, new_name
);
1301 if (driver
->dependentfiles
) {
1302 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1303 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1304 fstrcpy(new_name
, p
+1);
1305 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1310 architecture
= get_short_archi(driver
->environment
);
1312 /* jfm:7/16/2000 the client always sends the cversion=0.
1313 * The server should check which version the driver is by reading
1314 * the PE header of driver->driverpath.
1316 * For Windows 95/98 the version is 0 (so the value sent is correct)
1317 * For Windows NT (the architecture doesn't matter)
1318 * NT 3.1: cversion=0
1319 * NT 3.5/3.51: cversion=1
1323 if ((driver
->version
= get_correct_cversion(architecture
, driver
->driverpath
, user
, &err
)) == -1)
1329 /****************************************************************************
1330 ****************************************************************************/
1331 WERROR
clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
,
1332 uint32 level
, struct current_user
*user
)
1337 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1338 driver
=driver_abstract
.info_3
;
1339 return clean_up_driver_struct_level_3(driver
, user
);
1343 NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
;
1344 driver
=driver_abstract
.info_6
;
1345 return clean_up_driver_struct_level_6(driver
, user
);
1348 return WERR_INVALID_PARAM
;
1352 /****************************************************************************
1353 This function sucks and should be replaced. JRA.
1354 ****************************************************************************/
1356 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*dst
, NT_PRINTER_DRIVER_INFO_LEVEL_6
*src
)
1358 dst
->cversion
= src
->version
;
1360 fstrcpy( dst
->name
, src
->name
);
1361 fstrcpy( dst
->environment
, src
->environment
);
1362 fstrcpy( dst
->driverpath
, src
->driverpath
);
1363 fstrcpy( dst
->datafile
, src
->datafile
);
1364 fstrcpy( dst
->configfile
, src
->configfile
);
1365 fstrcpy( dst
->helpfile
, src
->helpfile
);
1366 fstrcpy( dst
->monitorname
, src
->monitorname
);
1367 fstrcpy( dst
->defaultdatatype
, src
->defaultdatatype
);
1368 dst
->dependentfiles
= src
->dependentfiles
;
1371 #if 0 /* Debugging function */
1373 static char* ffmt(unsigned char *c
){
1375 static char ffmt_str
[17];
1377 for (i
=0; i
<16; i
++) {
1378 if ((c
[i
] < ' ') || (c
[i
] > '~'))
1389 /****************************************************************************
1390 ****************************************************************************/
1391 BOOL
move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
, uint32 level
,
1392 struct current_user
*user
, WERROR
*perr
)
1394 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1395 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver
;
1396 const char *architecture
;
1401 connection_struct
*conn
;
1409 memset(inbuf
, '\0', sizeof(inbuf
));
1410 memset(outbuf
, '\0', sizeof(outbuf
));
1414 driver
=driver_abstract
.info_3
;
1415 else if (level
==6) {
1416 convert_level_6_to_level3(&converted_driver
, driver_abstract
.info_6
);
1417 driver
= &converted_driver
;
1419 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level
));
1423 architecture
= get_short_archi(driver
->environment
);
1426 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1427 * Note we must be root to do this.
1430 null_pw
= data_blob(NULL
, 0);
1431 fstrcpy(res_type
, "A:");
1433 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1437 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1438 *perr
= ntstatus_to_werror(nt_status
);
1443 * Save who we are - we are temporarily becoming the connection user.
1446 if (!become_user(conn
, conn
->vuid
)) {
1447 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1452 * make the directories version and version\driver_name
1453 * under the architecture directory.
1455 DEBUG(5,("Creating first directory\n"));
1456 slprintf(new_dir
, sizeof(new_dir
)-1, "%s/%d", architecture
, driver
->cversion
);
1457 mkdir_internal(conn
, new_dir
);
1459 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1460 * listed for this driver which has already been moved, skip it (note:
1461 * drivers may list the same file name several times. Then check if the
1462 * file already exists in archi\cversion\, if so, check that the version
1463 * info (or time stamps if version info is unavailable) is newer (or the
1464 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1465 * Otherwise, delete the file.
1467 * If a file is not moved to archi\cversion\ because of an error, all the
1468 * rest of the 'unmoved' driver files are removed from archi\. If one or
1469 * more of the driver's files was already moved to archi\cversion\, it
1470 * potentially leaves the driver in a partially updated state. Version
1471 * trauma will most likely occur if an client attempts to use any printer
1472 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1473 * done is appropriate... later JRR
1476 DEBUG(5,("Moving files now !\n"));
1478 if (driver
->driverpath
&& strlen(driver
->driverpath
)) {
1479 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->driverpath
);
1480 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->driverpath
);
1481 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1483 status
= rename_internals(conn
, new_name
, old_name
, 0, True
);
1484 if (!NT_STATUS_IS_OK(status
)) {
1485 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1486 new_name
, old_name
));
1487 *perr
= ntstatus_to_werror(status
);
1488 unlink_internals(conn
, 0, new_name
);
1493 unlink_internals(conn
, 0, new_name
);
1496 if (driver
->datafile
&& strlen(driver
->datafile
)) {
1497 if (!strequal(driver
->datafile
, driver
->driverpath
)) {
1498 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->datafile
);
1499 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->datafile
);
1500 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1502 status
= rename_internals(conn
, new_name
, old_name
, 0, True
);
1503 if (!NT_STATUS_IS_OK(status
)) {
1504 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1505 new_name
, old_name
));
1506 *perr
= ntstatus_to_werror(status
);
1507 unlink_internals(conn
, 0, new_name
);
1512 unlink_internals(conn
, 0, new_name
);
1516 if (driver
->configfile
&& strlen(driver
->configfile
)) {
1517 if (!strequal(driver
->configfile
, driver
->driverpath
) &&
1518 !strequal(driver
->configfile
, driver
->datafile
)) {
1519 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->configfile
);
1520 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->configfile
);
1521 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1523 status
= rename_internals(conn
, new_name
, old_name
, 0, True
);
1524 if (!NT_STATUS_IS_OK(status
)) {
1525 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1526 new_name
, old_name
));
1527 *perr
= ntstatus_to_werror(status
);
1528 unlink_internals(conn
, 0, new_name
);
1533 unlink_internals(conn
, 0, new_name
);
1537 if (driver
->helpfile
&& strlen(driver
->helpfile
)) {
1538 if (!strequal(driver
->helpfile
, driver
->driverpath
) &&
1539 !strequal(driver
->helpfile
, driver
->datafile
) &&
1540 !strequal(driver
->helpfile
, driver
->configfile
)) {
1541 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->helpfile
);
1542 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->helpfile
);
1543 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1545 status
= rename_internals(conn
, new_name
, old_name
, 0, True
);
1546 if (!NT_STATUS_IS_OK(status
)) {
1547 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1548 new_name
, old_name
));
1549 *perr
= ntstatus_to_werror(status
);
1550 unlink_internals(conn
, 0, new_name
);
1555 unlink_internals(conn
, 0, new_name
);
1559 if (driver
->dependentfiles
) {
1560 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1561 if (!strequal(driver
->dependentfiles
[i
], driver
->driverpath
) &&
1562 !strequal(driver
->dependentfiles
[i
], driver
->datafile
) &&
1563 !strequal(driver
->dependentfiles
[i
], driver
->configfile
) &&
1564 !strequal(driver
->dependentfiles
[i
], driver
->helpfile
)) {
1566 for (j
=0; j
< i
; j
++) {
1567 if (strequal(driver
->dependentfiles
[i
], driver
->dependentfiles
[j
])) {
1572 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->dependentfiles
[i
]);
1573 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->dependentfiles
[i
]);
1574 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1576 status
= rename_internals(conn
, new_name
, old_name
, 0, True
);
1577 if (!NT_STATUS_IS_OK(status
)) {
1578 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1579 new_name
, old_name
));
1580 *perr
= ntstatus_to_werror(status
);
1581 unlink_internals(conn
, 0, new_name
);
1586 unlink_internals(conn
, 0, new_name
);
1592 close_cnum(conn
, user
->vuid
);
1595 return ver
== -1 ? False
: True
;
1598 /****************************************************************************
1599 ****************************************************************************/
1600 static uint32
add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
)
1603 const char *architecture
;
1609 TDB_DATA kbuf
, dbuf
;
1611 architecture
= get_short_archi(driver
->environment
);
1613 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1614 * \\server is added in the rpc server layer.
1615 * It does make sense to NOT store the server's name in the printer TDB.
1618 slprintf(directory
, sizeof(directory
)-1, "\\print$\\%s\\%d\\", architecture
, driver
->cversion
);
1620 /* .inf files do not always list a file for each of the four standard files.
1621 * Don't prepend a path to a null filename, or client claims:
1622 * "The server on which the printer resides does not have a suitable
1623 * <printer driver name> printer driver installed. Click OK if you
1624 * wish to install the driver on your local machine."
1626 if (strlen(driver
->driverpath
)) {
1627 fstrcpy(temp_name
, driver
->driverpath
);
1628 slprintf(driver
->driverpath
, sizeof(driver
->driverpath
)-1, "%s%s", directory
, temp_name
);
1631 if (strlen(driver
->datafile
)) {
1632 fstrcpy(temp_name
, driver
->datafile
);
1633 slprintf(driver
->datafile
, sizeof(driver
->datafile
)-1, "%s%s", directory
, temp_name
);
1636 if (strlen(driver
->configfile
)) {
1637 fstrcpy(temp_name
, driver
->configfile
);
1638 slprintf(driver
->configfile
, sizeof(driver
->configfile
)-1, "%s%s", directory
, temp_name
);
1641 if (strlen(driver
->helpfile
)) {
1642 fstrcpy(temp_name
, driver
->helpfile
);
1643 slprintf(driver
->helpfile
, sizeof(driver
->helpfile
)-1, "%s%s", directory
, temp_name
);
1646 if (driver
->dependentfiles
) {
1647 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1648 fstrcpy(temp_name
, driver
->dependentfiles
[i
]);
1649 slprintf(driver
->dependentfiles
[i
], sizeof(driver
->dependentfiles
[i
])-1, "%s%s", directory
, temp_name
);
1653 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, driver
->cversion
, driver
->name
);
1655 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key
));
1662 len
+= tdb_pack(buf
+len
, buflen
-len
, "dffffffff",
1665 driver
->environment
,
1670 driver
->monitorname
,
1671 driver
->defaultdatatype
);
1673 if (driver
->dependentfiles
) {
1674 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1675 len
+= tdb_pack(buf
+len
, buflen
-len
, "f",
1676 driver
->dependentfiles
[i
]);
1680 if (len
!= buflen
) {
1683 tb
= (char *)Realloc(buf
, len
);
1685 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1696 kbuf
.dsize
= strlen(key
)+1;
1700 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
1704 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key
));
1710 /****************************************************************************
1711 ****************************************************************************/
1712 static uint32
add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
)
1714 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3
;
1717 info3
.cversion
= driver
->version
;
1718 fstrcpy(info3
.name
,driver
->name
);
1719 fstrcpy(info3
.environment
,driver
->environment
);
1720 fstrcpy(info3
.driverpath
,driver
->driverpath
);
1721 fstrcpy(info3
.datafile
,driver
->datafile
);
1722 fstrcpy(info3
.configfile
,driver
->configfile
);
1723 fstrcpy(info3
.helpfile
,driver
->helpfile
);
1724 fstrcpy(info3
.monitorname
,driver
->monitorname
);
1725 fstrcpy(info3
.defaultdatatype
,driver
->defaultdatatype
);
1726 info3
.dependentfiles
= driver
->dependentfiles
;
1728 return add_a_printer_driver_3(&info3
);
1732 /****************************************************************************
1733 ****************************************************************************/
1734 static WERROR
get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, const char *driver
, const char *arch
)
1736 NT_PRINTER_DRIVER_INFO_LEVEL_3 info
;
1740 fstrcpy(info
.name
, driver
);
1741 fstrcpy(info
.defaultdatatype
, "RAW");
1743 fstrcpy(info
.driverpath
, "");
1744 fstrcpy(info
.datafile
, "");
1745 fstrcpy(info
.configfile
, "");
1746 fstrcpy(info
.helpfile
, "");
1748 if ((info
.dependentfiles
=(fstring
*)malloc(2*sizeof(fstring
))) == NULL
)
1751 memset(info
.dependentfiles
, '\0', 2*sizeof(fstring
));
1752 fstrcpy(info
.dependentfiles
[0], "");
1754 *info_ptr
= memdup(&info
, sizeof(info
));
1759 /****************************************************************************
1760 ****************************************************************************/
1761 static WERROR
get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, fstring drivername
, const char *arch
, uint32 version
)
1763 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver
;
1764 TDB_DATA kbuf
, dbuf
;
1765 const char *architecture
;
1770 ZERO_STRUCT(driver
);
1772 architecture
= get_short_archi(arch
);
1774 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1776 if ( strcmp( architecture
, SPL_ARCH_WIN40
) == 0 )
1779 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX
, architecture
, version
, drivername
));
1781 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, version
, drivername
);
1784 kbuf
.dsize
= strlen(key
)+1;
1786 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
1788 return WERR_UNKNOWN_PRINTER_DRIVER
;
1790 len
+= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dffffffff",
1799 driver
.defaultdatatype
);
1802 while (len
< dbuf
.dsize
) {
1805 tddfs
= (fstring
*)Realloc(driver
.dependentfiles
,
1806 sizeof(fstring
)*(i
+2));
1807 if (tddfs
== NULL
) {
1808 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1811 else driver
.dependentfiles
= tddfs
;
1813 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "f",
1814 &driver
.dependentfiles
[i
]);
1818 if (driver
.dependentfiles
!= NULL
)
1819 fstrcpy(driver
.dependentfiles
[i
], "");
1821 SAFE_FREE(dbuf
.dptr
);
1823 if (len
!= dbuf
.dsize
) {
1824 SAFE_FREE(driver
.dependentfiles
);
1826 return get_a_printer_driver_3_default(info_ptr
, drivername
, arch
);
1829 *info_ptr
= (NT_PRINTER_DRIVER_INFO_LEVEL_3
*)memdup(&driver
, sizeof(driver
));
1834 /****************************************************************************
1835 Debugging function, dump at level 6 the struct in the logs.
1836 ****************************************************************************/
1838 static uint32
dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
1841 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
1844 DEBUG(20,("Dumping printer driver at level [%d]\n", level
));
1850 if (driver
.info_3
== NULL
)
1853 info3
=driver
.info_3
;
1855 DEBUGADD(20,("version:[%d]\n", info3
->cversion
));
1856 DEBUGADD(20,("name:[%s]\n", info3
->name
));
1857 DEBUGADD(20,("environment:[%s]\n", info3
->environment
));
1858 DEBUGADD(20,("driverpath:[%s]\n", info3
->driverpath
));
1859 DEBUGADD(20,("datafile:[%s]\n", info3
->datafile
));
1860 DEBUGADD(20,("configfile:[%s]\n", info3
->configfile
));
1861 DEBUGADD(20,("helpfile:[%s]\n", info3
->helpfile
));
1862 DEBUGADD(20,("monitorname:[%s]\n", info3
->monitorname
));
1863 DEBUGADD(20,("defaultdatatype:[%s]\n", info3
->defaultdatatype
));
1865 for (i
=0; info3
->dependentfiles
&&
1866 *info3
->dependentfiles
[i
]; i
++) {
1867 DEBUGADD(20,("dependentfile:[%s]\n",
1868 info3
->dependentfiles
[i
]));
1875 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level
));
1883 /****************************************************************************
1884 ****************************************************************************/
1885 int pack_devicemode(NT_DEVICEMODE
*nt_devmode
, char *buf
, int buflen
)
1889 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", nt_devmode
);
1894 len
+= tdb_pack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1895 nt_devmode
->devicename
,
1896 nt_devmode
->formname
,
1898 nt_devmode
->specversion
,
1899 nt_devmode
->driverversion
,
1901 nt_devmode
->driverextra
,
1902 nt_devmode
->orientation
,
1903 nt_devmode
->papersize
,
1904 nt_devmode
->paperlength
,
1905 nt_devmode
->paperwidth
,
1908 nt_devmode
->defaultsource
,
1909 nt_devmode
->printquality
,
1912 nt_devmode
->yresolution
,
1913 nt_devmode
->ttoption
,
1914 nt_devmode
->collate
,
1915 nt_devmode
->logpixels
,
1918 nt_devmode
->bitsperpel
,
1919 nt_devmode
->pelswidth
,
1920 nt_devmode
->pelsheight
,
1921 nt_devmode
->displayflags
,
1922 nt_devmode
->displayfrequency
,
1923 nt_devmode
->icmmethod
,
1924 nt_devmode
->icmintent
,
1925 nt_devmode
->mediatype
,
1926 nt_devmode
->dithertype
,
1927 nt_devmode
->reserved1
,
1928 nt_devmode
->reserved2
,
1929 nt_devmode
->panningwidth
,
1930 nt_devmode
->panningheight
,
1931 nt_devmode
->private);
1934 if (nt_devmode
->private) {
1935 len
+= tdb_pack(buf
+len
, buflen
-len
, "B",
1936 nt_devmode
->driverextra
,
1937 nt_devmode
->private);
1940 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode
->formname
));
1945 /****************************************************************************
1946 Pack all values in all printer keys
1947 ***************************************************************************/
1949 static int pack_values(NT_PRINTER_DATA
*data
, char *buf
, int buflen
)
1953 REGISTRY_VALUE
*val
;
1954 REGVAL_CTR
*val_ctr
;
1961 /* loop over all keys */
1963 for ( i
=0; i
<data
->num_keys
; i
++ ) {
1964 val_ctr
= &data
->keys
[i
].values
;
1965 num_values
= regval_ctr_numvals( val_ctr
);
1967 /* loop over all values */
1969 for ( j
=0; j
<num_values
; j
++ ) {
1970 /* pathname should be stored as <key>\<value> */
1972 val
= regval_ctr_specific_value( val_ctr
, j
);
1973 pstrcpy( path
, data
->keys
[i
].name
);
1974 pstrcat( path
, "\\" );
1975 pstrcat( path
, regval_name(val
) );
1977 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
1982 regval_data_p(val
) );
1989 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", NULL
);
1995 /****************************************************************************
1996 Delete a printer - this just deletes the printer info file, any open
1997 handles are not affected.
1998 ****************************************************************************/
2000 uint32
del_a_printer(char *sharename
)
2005 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
2008 kbuf
.dsize
=strlen(key
)+1;
2010 tdb_delete(tdb_printers
, kbuf
);
2014 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
2015 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
**, const char* sharename
);
2016 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**);
2017 /****************************************************************************
2018 ****************************************************************************/
2019 static WERROR
update_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
)
2025 TDB_DATA kbuf
, dbuf
;
2028 * in addprinter: no servername and the printer is the name
2029 * in setprinter: servername is \\server
2030 * and printer is \\server\\printer
2032 * Samba manages only local printers.
2033 * we currently don't support things like path=\\other_server\printer
2036 if (info
->servername
[0]!='\0') {
2037 trim_string(info
->printername
, info
->servername
, NULL
);
2038 trim_char(info
->printername
, '\\', '\0');
2039 info
->servername
[0]='\0';
2043 * JFM: one day I'll forget.
2044 * below that's info->portname because that's the SAMBA sharename
2045 * and I made NT 'thinks' it's the portname
2046 * the info->sharename is the thing you can name when you add a printer
2047 * that's the short-name when you create shared printer for 95/98
2048 * So I've made a limitation in SAMBA: you can only have 1 printer model
2049 * behind a SAMBA share.
2057 len
+= tdb_pack(buf
+len
, buflen
-len
, "dddddddddddfffffPfffff",
2060 info
->default_priority
,
2077 info
->printprocessor
,
2081 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
2083 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
2085 if (buflen
!= len
) {
2088 tb
= (char *)Realloc(buf
, len
);
2090 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2100 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, info
->sharename
);
2103 kbuf
.dsize
= strlen(key
)+1;
2107 ret
= (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) == 0? WERR_OK
: WERR_NOMEM
);
2110 if (!W_ERROR_IS_OK(ret
))
2111 DEBUG(8, ("error updating printer to tdb on disk\n"));
2115 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2116 info
->sharename
, info
->drivername
, info
->portname
, len
));
2122 /****************************************************************************
2123 Malloc and return an NT devicemode.
2124 ****************************************************************************/
2126 NT_DEVICEMODE
*construct_nt_devicemode(const fstring default_devicename
)
2129 char adevice
[MAXDEVICENAME
];
2130 NT_DEVICEMODE
*nt_devmode
= (NT_DEVICEMODE
*)malloc(sizeof(NT_DEVICEMODE
));
2132 if (nt_devmode
== NULL
) {
2133 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2137 ZERO_STRUCTP(nt_devmode
);
2139 safe_strcpy(adevice
, default_devicename
, sizeof(adevice
)-1);
2140 fstrcpy(nt_devmode
->devicename
, adevice
);
2142 fstrcpy(nt_devmode
->formname
, "Letter");
2144 nt_devmode
->specversion
= 0x0401;
2145 nt_devmode
->driverversion
= 0x0400;
2146 nt_devmode
->size
= 0x00DC;
2147 nt_devmode
->driverextra
= 0x0000;
2148 nt_devmode
->fields
= FORMNAME
| TTOPTION
| PRINTQUALITY
|
2149 DEFAULTSOURCE
| COPIES
| SCALE
|
2150 PAPERSIZE
| ORIENTATION
;
2151 nt_devmode
->orientation
= 1;
2152 nt_devmode
->papersize
= PAPER_LETTER
;
2153 nt_devmode
->paperlength
= 0;
2154 nt_devmode
->paperwidth
= 0;
2155 nt_devmode
->scale
= 0x64;
2156 nt_devmode
->copies
= 1;
2157 nt_devmode
->defaultsource
= BIN_FORMSOURCE
;
2158 nt_devmode
->printquality
= RES_HIGH
; /* 0x0258 */
2159 nt_devmode
->color
= COLOR_MONOCHROME
;
2160 nt_devmode
->duplex
= DUP_SIMPLEX
;
2161 nt_devmode
->yresolution
= 0;
2162 nt_devmode
->ttoption
= TT_SUBDEV
;
2163 nt_devmode
->collate
= COLLATE_FALSE
;
2164 nt_devmode
->icmmethod
= 0;
2165 nt_devmode
->icmintent
= 0;
2166 nt_devmode
->mediatype
= 0;
2167 nt_devmode
->dithertype
= 0;
2169 /* non utilisés par un driver d'imprimante */
2170 nt_devmode
->logpixels
= 0;
2171 nt_devmode
->bitsperpel
= 0;
2172 nt_devmode
->pelswidth
= 0;
2173 nt_devmode
->pelsheight
= 0;
2174 nt_devmode
->displayflags
= 0;
2175 nt_devmode
->displayfrequency
= 0;
2176 nt_devmode
->reserved1
= 0;
2177 nt_devmode
->reserved2
= 0;
2178 nt_devmode
->panningwidth
= 0;
2179 nt_devmode
->panningheight
= 0;
2181 nt_devmode
->private = NULL
;
2185 /****************************************************************************
2186 Deepcopy an NT devicemode.
2187 ****************************************************************************/
2189 NT_DEVICEMODE
*dup_nt_devicemode(NT_DEVICEMODE
*nt_devicemode
)
2191 NT_DEVICEMODE
*new_nt_devicemode
= NULL
;
2193 if ( !nt_devicemode
)
2196 if ((new_nt_devicemode
= (NT_DEVICEMODE
*)memdup(nt_devicemode
, sizeof(NT_DEVICEMODE
))) == NULL
) {
2197 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2201 new_nt_devicemode
->private = NULL
;
2202 if (nt_devicemode
->private != NULL
) {
2203 if ((new_nt_devicemode
->private = memdup(nt_devicemode
->private, nt_devicemode
->driverextra
)) == NULL
) {
2204 SAFE_FREE(new_nt_devicemode
);
2205 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2210 return new_nt_devicemode
;
2213 /****************************************************************************
2214 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2215 ****************************************************************************/
2217 void free_nt_devicemode(NT_DEVICEMODE
**devmode_ptr
)
2219 NT_DEVICEMODE
*nt_devmode
= *devmode_ptr
;
2221 if(nt_devmode
== NULL
)
2224 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2226 SAFE_FREE(nt_devmode
->private);
2227 SAFE_FREE(*devmode_ptr
);
2230 /****************************************************************************
2231 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2232 ****************************************************************************/
2233 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
)
2235 NT_PRINTER_INFO_LEVEL_2
*info
= *info_ptr
;
2236 NT_PRINTER_DATA
*data
;
2242 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2244 free_nt_devicemode(&info
->devmode
);
2246 /* clean up all registry keys */
2249 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2250 SAFE_FREE( data
->keys
[i
].name
);
2251 regval_ctr_destroy( &data
->keys
[i
].values
);
2253 SAFE_FREE( data
->keys
);
2255 /* finally the top level structure */
2257 SAFE_FREE( *info_ptr
);
2261 /****************************************************************************
2262 ****************************************************************************/
2263 int unpack_devicemode(NT_DEVICEMODE
**nt_devmode
, char *buf
, int buflen
)
2267 NT_DEVICEMODE devmode
;
2269 ZERO_STRUCT(devmode
);
2271 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2273 if (!*nt_devmode
) return len
;
2275 len
+= tdb_unpack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2279 &devmode
.specversion
,
2280 &devmode
.driverversion
,
2282 &devmode
.driverextra
,
2283 &devmode
.orientation
,
2285 &devmode
.paperlength
,
2286 &devmode
.paperwidth
,
2289 &devmode
.defaultsource
,
2290 &devmode
.printquality
,
2293 &devmode
.yresolution
,
2299 &devmode
.bitsperpel
,
2301 &devmode
.pelsheight
,
2302 &devmode
.displayflags
,
2303 &devmode
.displayfrequency
,
2307 &devmode
.dithertype
,
2310 &devmode
.panningwidth
,
2311 &devmode
.panningheight
,
2314 if (devmode
.private) {
2315 /* the len in tdb_unpack is an int value and
2316 * devmode.driverextra is only a short
2318 len
+= tdb_unpack(buf
+len
, buflen
-len
, "B", &extra_len
, &devmode
.private);
2319 devmode
.driverextra
=(uint16
)extra_len
;
2321 /* check to catch an invalid TDB entry so we don't segfault */
2322 if (devmode
.driverextra
== 0) {
2323 devmode
.private = NULL
;
2327 *nt_devmode
= (NT_DEVICEMODE
*)memdup(&devmode
, sizeof(devmode
));
2329 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode
.devicename
, devmode
.formname
));
2330 if (devmode
.private)
2331 DEBUG(8,("with a private section of %d bytes\n", devmode
.driverextra
));
2336 /****************************************************************************
2337 Allocate and initialize a new slot.
2338 ***************************************************************************/
2340 static int add_new_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2345 if ( !data
|| !name
)
2348 /* allocate another slot in the NT_PRINTER_KEY array */
2350 d
= Realloc( data
->keys
, sizeof(NT_PRINTER_KEY
)*(data
->num_keys
+1) );
2354 key_index
= data
->num_keys
;
2356 /* initialze new key */
2359 data
->keys
[key_index
].name
= strdup( name
);
2361 ZERO_STRUCTP( &data
->keys
[key_index
].values
);
2363 regval_ctr_init( &data
->keys
[key_index
].values
);
2365 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name
));
2370 /****************************************************************************
2371 search for a registry key name in the existing printer data
2372 ***************************************************************************/
2374 int lookup_printerkey( NT_PRINTER_DATA
*data
, const char *name
)
2379 if ( !data
|| !name
)
2382 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name
));
2384 /* loop over all existing keys */
2386 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2387 if ( strequal(data
->keys
[i
].name
, name
) ) {
2388 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name
));
2398 /****************************************************************************
2399 ***************************************************************************/
2401 uint32
get_printer_subkeys( NT_PRINTER_DATA
*data
, const char* key
, fstring
**subkeys
)
2405 int num_subkeys
= 0;
2407 fstring
*ptr
, *subkeys_ptr
= NULL
;
2413 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2414 if ( StrnCaseCmp(data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2415 /* match sure it is a subkey and not the key itself */
2417 key_len
= strlen( key
);
2418 if ( strlen(data
->keys
[i
].name
) == key_len
)
2421 /* get subkey path */
2423 p
= data
->keys
[i
].name
+ key_len
;
2426 fstrcpy( subkeyname
, p
);
2427 if ( (p
= strchr( subkeyname
, '\\' )) )
2430 /* don't add a key more than once */
2432 for ( j
=0; j
<num_subkeys
; j
++ ) {
2433 if ( strequal( subkeys_ptr
[j
], subkeyname
) )
2437 if ( j
!= num_subkeys
)
2440 /* found a match, so allocate space and copy the name */
2442 if ( !(ptr
= Realloc( subkeys_ptr
, (num_subkeys
+2)*sizeof(fstring
))) ) {
2443 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2445 SAFE_FREE( subkeys
);
2450 fstrcpy( subkeys_ptr
[num_subkeys
], subkeyname
);
2456 /* tag of the end */
2459 fstrcpy(subkeys_ptr
[num_subkeys
], "" );
2461 *subkeys
= subkeys_ptr
;
2467 static void map_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2470 smb_ucs2_t conv_str
[1024];
2473 regval_ctr_delvalue(ctr
, val_name
);
2474 str_size
= push_ucs2(NULL
, conv_str
, sz
, sizeof(conv_str
),
2475 STR_TERMINATE
| STR_NOALIGN
);
2476 regval_ctr_addvalue(ctr
, val_name
, REG_SZ
,
2477 (char *) conv_str
, str_size
);
2480 static void map_dword_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2483 regval_ctr_delvalue(ctr
, val_name
);
2484 regval_ctr_addvalue(ctr
, val_name
, REG_DWORD
,
2485 (char *) &dword
, sizeof(dword
));
2488 static void map_bool_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2491 uint8 bin_bool
= (b
? 1 : 0);
2492 regval_ctr_delvalue(ctr
, val_name
);
2493 regval_ctr_addvalue(ctr
, val_name
, REG_BINARY
,
2494 (char *) &bin_bool
, sizeof(bin_bool
));
2497 static void map_single_multi_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2498 const char *multi_sz
)
2500 smb_ucs2_t
*conv_strs
= NULL
;
2503 /* a multi-sz has to have a null string terminator, i.e., the last
2504 string must be followed by two nulls */
2505 str_size
= (strlen(multi_sz
) + 2) * sizeof(smb_ucs2_t
);
2506 conv_strs
= calloc(str_size
, 1);
2508 push_ucs2(NULL
, conv_strs
, multi_sz
, str_size
,
2509 STR_TERMINATE
| STR_NOALIGN
);
2511 regval_ctr_delvalue(ctr
, val_name
);
2512 regval_ctr_addvalue(ctr
, val_name
, REG_MULTI_SZ
,
2513 (char *) conv_strs
, str_size
);
2514 safe_free(conv_strs
);
2518 /****************************************************************************
2519 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2521 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2522 * @return BOOL indicating success or failure
2523 ***************************************************************************/
2525 static BOOL
map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2
*info2
)
2527 REGVAL_CTR
*ctr
= NULL
;
2529 char *allocated_string
= NULL
;
2530 const char *ascii_str
;
2533 if ((i
= lookup_printerkey(&info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2534 i
= add_new_printer_key(&info2
->data
, SPOOL_DSSPOOLER_KEY
);
2535 ctr
= &info2
->data
.keys
[i
].values
;
2537 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTERNAME
, info2
->sharename
);
2538 map_sz_into_ctr(ctr
, SPOOL_REG_SHORTSERVERNAME
, global_myname());
2540 get_mydnsfullname(longname
);
2541 map_sz_into_ctr(ctr
, SPOOL_REG_SERVERNAME
, longname
);
2543 asprintf(&allocated_string
, "\\\\%s\\%s", longname
, info2
->sharename
);
2544 map_sz_into_ctr(ctr
, SPOOL_REG_UNCNAME
, allocated_string
);
2545 SAFE_FREE(allocated_string
);
2547 map_dword_into_ctr(ctr
, SPOOL_REG_VERSIONNUMBER
, 4);
2548 map_sz_into_ctr(ctr
, SPOOL_REG_DRIVERNAME
, info2
->drivername
);
2549 map_sz_into_ctr(ctr
, SPOOL_REG_LOCATION
, info2
->location
);
2550 map_sz_into_ctr(ctr
, SPOOL_REG_DESCRIPTION
, info2
->comment
);
2551 map_single_multi_sz_into_ctr(ctr
, SPOOL_REG_PORTNAME
, info2
->portname
);
2552 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSEPARATORFILE
, info2
->sepfile
);
2553 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTSTARTTIME
, info2
->starttime
);
2554 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTENDTIME
, info2
->untiltime
);
2555 map_dword_into_ctr(ctr
, SPOOL_REG_PRIORITY
, info2
->priority
);
2557 map_bool_into_ctr(ctr
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
2558 (info2
->attributes
&
2559 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
2561 switch (info2
->attributes
& 0x3) {
2563 ascii_str
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
2566 ascii_str
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
2569 ascii_str
= SPOOL_REGVAL_PRINTDIRECT
;
2572 ascii_str
= "unknown";
2574 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSPOOLING
, ascii_str
);
2579 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2
*info2
, GUID guid
)
2582 REGVAL_CTR
*ctr
=NULL
;
2584 /* find the DsSpooler key */
2585 if ((i
= lookup_printerkey(&info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2586 i
= add_new_printer_key(&info2
->data
, SPOOL_DSSPOOLER_KEY
);
2587 ctr
= &info2
->data
.keys
[i
].values
;
2589 regval_ctr_delvalue(ctr
, "objectGUID");
2590 regval_ctr_addvalue(ctr
, "objectGUID", REG_BINARY
,
2591 (char *) &guid
, sizeof(GUID
));
2594 static WERROR
publish_it(NT_PRINTER_INFO_LEVEL
*printer
)
2597 TALLOC_CTX
*ctx
= talloc_init("publish_it");
2598 ADS_MODLIST mods
= ads_init_mods(ctx
);
2599 char *prt_dn
= NULL
, *srv_dn
, *srv_cn_0
;
2600 char *srv_dn_utf8
, **srv_cn_utf8
;
2603 const char *attrs
[] = {"objectGUID", NULL
};
2605 WERROR win_rc
= WERR_OK
;
2608 /* set the DsSpooler info and attributes */
2609 if (!(map_nt_printer_info2_to_dsspooler(printer
->info_2
)))
2611 printer
->info_2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
2612 win_rc
= mod_a_printer(*printer
, 2);
2613 if (!W_ERROR_IS_OK(win_rc
)) {
2614 DEBUG(3, ("err %d saving data\n",
2615 W_ERROR_V(win_rc
)));
2619 /* Build the ads mods */
2620 get_local_printer_publishing_data(ctx
, &mods
,
2621 &printer
->info_2
->data
);
2622 ads_mod_str(ctx
, &mods
, SPOOL_REG_PRINTERNAME
,
2623 printer
->info_2
->sharename
);
2625 /* initial ads structure */
2627 ads
= ads_init(NULL
, NULL
, NULL
);
2629 DEBUG(3, ("ads_init() failed\n"));
2630 return WERR_SERVER_UNAVAILABLE
;
2632 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
2633 SAFE_FREE(ads
->auth
.password
);
2634 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
2637 /* ads_connect() will find the DC for us */
2638 ads_rc
= ads_connect(ads
);
2639 if (!ADS_ERR_OK(ads_rc
)) {
2640 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
2642 return WERR_ACCESS_DENIED
;
2645 /* figure out where to publish */
2646 ads_find_machine_acct(ads
, &res
, global_myname());
2648 /* We use ldap_get_dn here as we need the answer
2649 * in utf8 to call ldap_explode_dn(). JRA. */
2651 srv_dn_utf8
= ldap_get_dn(ads
->ld
, res
);
2654 return WERR_SERVER_UNAVAILABLE
;
2656 ads_msgfree(ads
, res
);
2657 srv_cn_utf8
= ldap_explode_dn(srv_dn_utf8
, 1);
2659 ldap_memfree(srv_dn_utf8
);
2661 return WERR_SERVER_UNAVAILABLE
;
2663 /* Now convert to CH_UNIX. */
2664 if (pull_utf8_allocate(&srv_dn
, srv_dn_utf8
) == (size_t)-1) {
2665 ldap_memfree(srv_dn_utf8
);
2666 ldap_memfree(srv_cn_utf8
);
2668 return WERR_SERVER_UNAVAILABLE
;
2670 if (pull_utf8_allocate(&srv_cn_0
, srv_cn_utf8
[0]) == (size_t)-1) {
2671 ldap_memfree(srv_dn_utf8
);
2672 ldap_memfree(srv_cn_utf8
);
2675 return WERR_SERVER_UNAVAILABLE
;
2678 ldap_memfree(srv_dn_utf8
);
2679 ldap_memfree(srv_cn_utf8
);
2681 asprintf(&prt_dn
, "cn=%s-%s,%s", srv_cn_0
,
2682 printer
->info_2
->sharename
, srv_dn
);
2685 SAFE_FREE(srv_cn_0
);
2688 ads_rc
= ads_add_printer_entry(ads
, prt_dn
, ctx
, &mods
);
2689 if (LDAP_ALREADY_EXISTS
== ads_rc
.err
.rc
)
2690 ads_rc
= ads_mod_printer_entry(ads
, prt_dn
, ctx
,&mods
);
2692 /* retreive the guid and store it locally */
2693 if (ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
2694 ads_memfree(ads
, prt_dn
);
2695 ads_pull_guid(ads
, res
, &guid
);
2696 ads_msgfree(ads
, res
);
2697 store_printer_guid(printer
->info_2
, guid
);
2698 win_rc
= mod_a_printer(*printer
, 2);
2707 WERROR
unpublish_it(NT_PRINTER_INFO_LEVEL
*printer
)
2712 char *prt_dn
= NULL
;
2715 printer
->info_2
->attributes
^= PRINTER_ATTRIBUTE_PUBLISHED
;
2716 win_rc
= mod_a_printer(*printer
, 2);
2717 if (!W_ERROR_IS_OK(win_rc
)) {
2718 DEBUG(3, ("err %d saving data\n",
2719 W_ERROR_V(win_rc
)));
2723 ads
= ads_init(NULL
, NULL
, NULL
);
2725 DEBUG(3, ("ads_init() failed\n"));
2726 return WERR_SERVER_UNAVAILABLE
;
2728 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
2729 SAFE_FREE(ads
->auth
.password
);
2730 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
2733 /* ads_connect() will find the DC for us */
2734 ads_rc
= ads_connect(ads
);
2735 if (!ADS_ERR_OK(ads_rc
)) {
2736 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
2738 return WERR_ACCESS_DENIED
;
2741 /* remove the printer from the directory */
2742 ads_rc
= ads_find_printer_on_server(ads
, &res
,
2743 printer
->info_2
->sharename
, global_myname());
2744 if (ADS_ERR_OK(ads_rc
) && ads_count_replies(ads
, res
)) {
2745 prt_dn
= ads_get_dn(ads
, res
);
2746 ads_msgfree(ads
, res
);
2747 ads_rc
= ads_del_dn(ads
, prt_dn
);
2748 ads_memfree(ads
, prt_dn
);
2755 /****************************************************************************
2756 * Publish a printer in the directory
2758 * @param snum describing printer service
2759 * @return WERROR indicating status of publishing
2760 ***************************************************************************/
2762 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
2764 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2767 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
2768 if (!W_ERROR_IS_OK(win_rc
))
2772 case SPOOL_DS_PUBLISH
:
2773 case SPOOL_DS_UPDATE
:
2774 win_rc
= publish_it(printer
);
2776 case SPOOL_DS_UNPUBLISH
:
2777 win_rc
= unpublish_it(printer
);
2780 win_rc
= WERR_NOT_SUPPORTED
;
2784 free_a_printer(&printer
, 2);
2788 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
, GUID
*guid
)
2790 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2792 REGISTRY_VALUE
*guid_val
;
2797 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
2798 if (!W_ERROR_IS_OK(win_rc
))
2801 if (!(printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
))
2804 if ((i
= lookup_printerkey(&printer
->info_2
->data
,
2805 SPOOL_DSSPOOLER_KEY
)) < 0)
2808 if (!(ctr
= &printer
->info_2
->data
.keys
[i
].values
)) {
2812 if (!(guid_val
= regval_ctr_getvalue(ctr
, "objectGUID"))) {
2816 if (regval_size(guid_val
) == sizeof(GUID
))
2817 memcpy(guid
, regval_data_p(guid_val
), sizeof(GUID
));
2823 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
2827 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
, GUID
*guid
)
2832 /****************************************************************************
2833 ***************************************************************************/
2835 WERROR
delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
)
2837 NT_PRINTER_DATA
*data
;
2839 int removed_keys
= 0;
2843 empty_slot
= data
->num_keys
;
2846 return WERR_INVALID_PARAM
;
2848 /* remove all keys */
2850 if ( !strlen(key
) ) {
2851 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2852 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2853 data
->keys
[i
].name
));
2855 SAFE_FREE( data
->keys
[i
].name
);
2856 regval_ctr_destroy( &data
->keys
[i
].values
);
2859 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2862 SAFE_FREE( data
->keys
);
2863 ZERO_STRUCTP( data
);
2868 /* remove a specific key (and all subkeys) */
2870 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2871 if ( StrnCaseCmp( data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2872 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2873 data
->keys
[i
].name
));
2875 SAFE_FREE( data
->keys
[i
].name
);
2876 regval_ctr_destroy( &data
->keys
[i
].values
);
2878 /* mark the slot as empty */
2880 ZERO_STRUCTP( &data
->keys
[i
] );
2884 /* find the first empty slot */
2886 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2887 if ( !data
->keys
[i
].name
) {
2894 if ( i
== data
->num_keys
)
2895 /* nothing was removed */
2896 return WERR_INVALID_PARAM
;
2898 /* move everything down */
2900 for ( i
=empty_slot
+1; i
<data
->num_keys
; i
++ ) {
2901 if ( data
->keys
[i
].name
) {
2902 memcpy( &data
->keys
[empty_slot
], &data
->keys
[i
], sizeof(NT_PRINTER_KEY
) );
2903 ZERO_STRUCTP( &data
->keys
[i
] );
2911 data
->num_keys
-= removed_keys
;
2913 /* sanity check to see if anything is left */
2915 if ( !data
->num_keys
) {
2916 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2
->printername
));
2918 SAFE_FREE( data
->keys
);
2919 ZERO_STRUCTP( data
);
2925 /****************************************************************************
2926 ***************************************************************************/
2928 WERROR
delete_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
2930 WERROR result
= WERR_OK
;
2933 /* we must have names on non-zero length */
2935 if ( !key
|| !*key
|| !value
|| !*value
)
2936 return WERR_INVALID_NAME
;
2938 /* find the printer key first */
2940 key_index
= lookup_printerkey( &p2
->data
, key
);
2941 if ( key_index
== -1 )
2944 /* make sure the value exists so we can return the correct error code */
2946 if ( !regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
) )
2947 return WERR_BADFILE
;
2949 regval_ctr_delvalue( &p2
->data
.keys
[key_index
].values
, value
);
2951 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2957 /****************************************************************************
2958 ***************************************************************************/
2960 WERROR
add_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
,
2961 uint32 type
, uint8
*data
, int real_len
)
2963 WERROR result
= WERR_OK
;
2966 /* we must have names on non-zero length */
2968 if ( !key
|| !*key
|| !value
|| !*value
)
2969 return WERR_INVALID_NAME
;
2971 /* find the printer key first */
2973 key_index
= lookup_printerkey( &p2
->data
, key
);
2974 if ( key_index
== -1 )
2975 key_index
= add_new_printer_key( &p2
->data
, key
);
2977 if ( key_index
== -1 )
2980 regval_ctr_addvalue( &p2
->data
.keys
[key_index
].values
, value
,
2981 type
, (const char *)data
, real_len
);
2983 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
2984 key
, value
, type
, real_len
));
2989 /****************************************************************************
2990 ***************************************************************************/
2992 REGISTRY_VALUE
* get_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
2996 if ( (key_index
= lookup_printerkey( &p2
->data
, key
)) == -1 )
2999 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3002 return regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
);
3005 /****************************************************************************
3006 Unpack a list of registry values frem the TDB
3007 ***************************************************************************/
3009 static int unpack_values(NT_PRINTER_DATA
*printer_data
, char *buf
, int buflen
)
3013 pstring string
, valuename
, keyname
;
3017 REGISTRY_VALUE
*regval_p
;
3020 /* add the "PrinterDriverData" key first for performance reasons */
3022 add_new_printer_key( printer_data
, SPOOL_PRINTERDATA_KEY
);
3024 /* loop and unpack the rest of the registry values */
3028 /* check to see if there are any more registry values */
3030 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", ®val_p
);
3034 /* unpack the next regval */
3036 len
+= tdb_unpack(buf
+len
, buflen
-len
, "fdB",
3043 * break of the keyname from the value name.
3044 * Should only be one '\' in the string returned.
3047 str
= strrchr( string
, '\\');
3049 /* Put in "PrinterDriverData" is no key specified */
3052 pstrcpy( keyname
, SPOOL_PRINTERDATA_KEY
);
3053 pstrcpy( valuename
, string
);
3057 pstrcpy( keyname
, string
);
3058 pstrcpy( valuename
, str
+1 );
3061 /* see if we need a new key */
3063 if ( (key_index
=lookup_printerkey( printer_data
, keyname
)) == -1 )
3064 key_index
= add_new_printer_key( printer_data
, keyname
);
3066 if ( key_index
== -1 ) {
3067 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3072 /* add the new value */
3074 regval_ctr_addvalue( &printer_data
->keys
[key_index
].values
, valuename
, type
, (const char *)data_p
, size
);
3076 SAFE_FREE(data_p
); /* 'B' option to tdbpack does a malloc() */
3078 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname
, valuename
, size
));
3084 /****************************************************************************
3085 ***************************************************************************/
3087 static void map_to_os2_driver(fstring drivername
)
3089 static BOOL initialised
=False
;
3090 static fstring last_from
,last_to
;
3091 char *mapfile
= lp_os2_driver_map();
3092 char **lines
= NULL
;
3096 if (!strlen(drivername
))
3103 *last_from
= *last_to
= 0;
3107 if (strequal(drivername
,last_from
)) {
3108 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,last_to
));
3109 fstrcpy(drivername
,last_to
);
3113 lines
= file_lines_load(mapfile
, &numlines
);
3114 if (numlines
== 0) {
3115 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile
));
3119 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
3121 for( i
= 0; i
< numlines
; i
++) {
3122 char *nt_name
= lines
[i
];
3123 char *os2_name
= strchr(nt_name
,'=');
3130 while (isspace(*nt_name
))
3133 if (!*nt_name
|| strchr("#;",*nt_name
))
3137 int l
= strlen(nt_name
);
3138 while (l
&& isspace(nt_name
[l
-1])) {
3144 while (isspace(*os2_name
))
3148 int l
= strlen(os2_name
);
3149 while (l
&& isspace(os2_name
[l
-1])) {
3155 if (strequal(nt_name
,drivername
)) {
3156 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername
,os2_name
));
3157 fstrcpy(last_from
,drivername
);
3158 fstrcpy(last_to
,os2_name
);
3159 fstrcpy(drivername
,os2_name
);
3160 file_lines_free(lines
);
3165 file_lines_free(lines
);
3168 /****************************************************************************
3169 Get a default printer info 2 struct.
3170 ****************************************************************************/
3171 static WERROR
get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, const char *sharename
)
3174 NT_PRINTER_INFO_LEVEL_2 info
;
3178 snum
= lp_servicenumber(sharename
);
3180 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", get_called_name());
3181 slprintf(info
.printername
, sizeof(info
.printername
)-1, "\\\\%s\\%s",
3182 get_called_name(), sharename
);
3183 fstrcpy(info
.sharename
, sharename
);
3184 fstrcpy(info
.portname
, SAMBA_PRINTER_PORT_NAME
);
3186 /* by setting the driver name to an empty string, a local NT admin
3187 can now run the **local** APW to install a local printer driver
3188 for a Samba shared printer in 2.2. Without this, drivers **must** be
3189 installed on the Samba server for NT clients --jerry */
3190 #if 0 /* JERRY --do not uncomment-- */
3191 if (!*info
.drivername
)
3192 fstrcpy(info
.drivername
, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3196 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info
.drivername
));
3198 pstrcpy(info
.comment
, "");
3199 fstrcpy(info
.printprocessor
, "winprint");
3200 fstrcpy(info
.datatype
, "RAW");
3202 info
.attributes
= PRINTER_ATTRIBUTE_SAMBA
;
3204 info
.starttime
= 0; /* Minutes since 12:00am GMT */
3205 info
.untiltime
= 0; /* Minutes since 12:00am GMT */
3207 info
.default_priority
= 1;
3208 info
.setuptime
= (uint32
)time(NULL
);
3211 * I changed this as I think it is better to have a generic
3212 * DEVMODE than to crash Win2k explorer.exe --jerry
3213 * See the HP Deskjet 990c Win2k drivers for an example.
3215 * However the default devmode appears to cause problems
3216 * with the HP CLJ 8500 PCL driver. Hence the addition of
3217 * the "default devmode" parameter --jerry 22/01/2002
3220 if (lp_default_devmode(snum
)) {
3221 if ((info
.devmode
= construct_nt_devicemode(info
.printername
)) == NULL
)
3225 info
.devmode
= NULL
;
3228 /* This will get the current RPC talloc context, but we should be
3229 passing this as a parameter... fixme... JRA ! */
3231 if (!nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
))
3234 *info_ptr
= (NT_PRINTER_INFO_LEVEL_2
*)memdup(&info
, sizeof(info
));
3236 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3244 free_nt_devicemode(&info
.devmode
);
3245 return WERR_ACCESS_DENIED
;
3248 /****************************************************************************
3249 ****************************************************************************/
3250 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, const char *sharename
)
3253 NT_PRINTER_INFO_LEVEL_2 info
;
3255 TDB_DATA kbuf
, dbuf
;
3256 fstring printername
;
3257 char adevice
[MAXDEVICENAME
];
3261 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
3264 kbuf
.dsize
= strlen(key
)+1;
3266 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
3268 return get_a_printer_2_default(info_ptr
, sharename
);
3270 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "dddddddddddfffffPfffff",
3273 &info
.default_priority
,
3290 info
.printprocessor
,
3294 /* Samba has to have shared raw drivers. */
3295 info
.attributes
= PRINTER_ATTRIBUTE_SAMBA
;
3297 /* Restore the stripped strings. */
3298 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", get_called_name());
3299 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", get_called_name(),
3301 fstrcpy(info
.printername
, printername
);
3303 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3306 * Some client drivers freak out if there is a NULL devmode
3307 * (probably the driver is not checking before accessing
3308 * the devmode pointer) --jerry
3310 * See comments in get_a_printer_2_default()
3313 if (lp_default_devmode(lp_servicenumber(sharename
)) && !info
.devmode
) {
3314 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3316 info
.devmode
= construct_nt_devicemode(printername
);
3319 safe_strcpy(adevice
, info
.printername
, sizeof(adevice
)-1);
3321 fstrcpy(info
.devmode
->devicename
, adevice
);
3324 len
+= unpack_values( &info
.data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3326 /* This will get the current RPC talloc context, but we should be
3327 passing this as a parameter... fixme... JRA ! */
3329 nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
);
3331 /* Fix for OS/2 drivers. */
3333 if (get_remote_arch() == RA_OS2
)
3334 map_to_os2_driver(info
.drivername
);
3336 SAFE_FREE(dbuf
.dptr
);
3337 *info_ptr
=memdup(&info
, sizeof(info
));
3339 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3340 sharename
, info
.printername
, info
.drivername
));
3345 /****************************************************************************
3346 Debugging function, dump at level 6 the struct in the logs.
3347 ****************************************************************************/
3348 static uint32
dump_a_printer(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3351 NT_PRINTER_INFO_LEVEL_2
*info2
;
3353 DEBUG(106,("Dumping printer at level [%d]\n", level
));
3358 if (printer
.info_2
== NULL
)
3362 info2
=printer
.info_2
;
3364 DEBUGADD(106,("attributes:[%d]\n", info2
->attributes
));
3365 DEBUGADD(106,("priority:[%d]\n", info2
->priority
));
3366 DEBUGADD(106,("default_priority:[%d]\n", info2
->default_priority
));
3367 DEBUGADD(106,("starttime:[%d]\n", info2
->starttime
));
3368 DEBUGADD(106,("untiltime:[%d]\n", info2
->untiltime
));
3369 DEBUGADD(106,("status:[%d]\n", info2
->status
));
3370 DEBUGADD(106,("cjobs:[%d]\n", info2
->cjobs
));
3371 DEBUGADD(106,("averageppm:[%d]\n", info2
->averageppm
));
3372 DEBUGADD(106,("changeid:[%d]\n", info2
->changeid
));
3373 DEBUGADD(106,("c_setprinter:[%d]\n", info2
->c_setprinter
));
3374 DEBUGADD(106,("setuptime:[%d]\n", info2
->setuptime
));
3376 DEBUGADD(106,("servername:[%s]\n", info2
->servername
));
3377 DEBUGADD(106,("printername:[%s]\n", info2
->printername
));
3378 DEBUGADD(106,("sharename:[%s]\n", info2
->sharename
));
3379 DEBUGADD(106,("portname:[%s]\n", info2
->portname
));
3380 DEBUGADD(106,("drivername:[%s]\n", info2
->drivername
));
3381 DEBUGADD(106,("comment:[%s]\n", info2
->comment
));
3382 DEBUGADD(106,("location:[%s]\n", info2
->location
));
3383 DEBUGADD(106,("sepfile:[%s]\n", info2
->sepfile
));
3384 DEBUGADD(106,("printprocessor:[%s]\n", info2
->printprocessor
));
3385 DEBUGADD(106,("datatype:[%s]\n", info2
->datatype
));
3386 DEBUGADD(106,("parameters:[%s]\n", info2
->parameters
));
3392 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level
));
3400 /****************************************************************************
3401 Update the changeid time.
3402 This is SO NASTY as some drivers need this to change, others need it
3403 static. This value will change every second, and I must hope that this
3404 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3406 ****************************************************************************/
3408 static uint32
rev_changeid(void)
3412 get_process_uptime(&tv
);
3415 /* Return changeid as msec since spooler restart */
3416 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
3419 * This setting seems to work well but is too untested
3420 * to replace the above calculation. Left in for experiementation
3421 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3423 return tv
.tv_sec
* 10 + tv
.tv_usec
/ 100000;
3428 * The function below are the high level ones.
3429 * only those ones must be called from the spoolss code.
3433 /****************************************************************************
3434 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3435 ****************************************************************************/
3437 WERROR
mod_a_printer(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3441 dump_a_printer(printer
, level
);
3444 * invalidate cache for all open handles to this printer.
3445 * cache for a given handle will be updated on the next
3449 invalidate_printer_hnd_cache( printer
.info_2
->sharename
);
3455 * Update the changestamp. Emperical tests show that the
3456 * ChangeID is always updated,but c_setprinter is
3457 * global spooler variable (not per printer).
3460 /* ChangeID **must** be increasing over the lifetime
3461 of client's spoolss service in order for the
3462 client's cache to show updates */
3464 printer
.info_2
->changeid
= rev_changeid();
3467 * Because one day someone will ask:
3468 * NT->NT An admin connection to a remote
3469 * printer show changes imeediately in
3470 * the properities dialog
3472 * A non-admin connection will only show the
3473 * changes after viewing the properites page
3474 * 2 times. Seems to be related to a
3475 * race condition in the client between the spooler
3476 * updating the local cache and the Explorer.exe GUI
3477 * actually displaying the properties.
3479 * This is fixed in Win2k. admin/non-admin
3480 * connections both display changes immediately.
3485 result
=update_a_printer_2(printer
.info_2
);
3490 result
=WERR_UNKNOWN_LEVEL
;
3497 /****************************************************************************
3498 Initialize printer devmode & data with previously saved driver init values.
3499 ****************************************************************************/
3501 static BOOL
set_driver_init_2( NT_PRINTER_INFO_LEVEL_2
*info_ptr
)
3505 TDB_DATA kbuf
, dbuf
;
3506 NT_PRINTER_INFO_LEVEL_2 info
;
3512 * Delete any printer data 'values' already set. When called for driver
3513 * replace, there will generally be some, but during an add printer, there
3514 * should not be any (if there are delete them).
3517 delete_all_printer_data( info_ptr
, "" );
3519 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info_ptr
->drivername
);
3522 kbuf
.dsize
= strlen(key
)+1;
3524 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
3527 * When changing to a driver that has no init info in the tdb, remove
3528 * the previous drivers init info and leave the new on blank.
3530 free_nt_devicemode(&info_ptr
->devmode
);
3535 * Get the saved DEVMODE..
3538 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3541 * The saved DEVMODE contains the devicename from the printer used during
3542 * the initialization save. Change it to reflect the new printer.
3545 if ( info
.devmode
) {
3546 ZERO_STRUCT(info
.devmode
->devicename
);
3547 fstrcpy(info
.devmode
->devicename
, info_ptr
->printername
);
3551 * NT/2k does not change out the entire DeviceMode of a printer
3552 * when changing the driver. Only the driverextra, private, &
3553 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3555 * Later examination revealed that Windows NT/2k does reset the
3556 * the printer's device mode, bit **only** when you change a
3557 * property of the device mode such as the page orientation.
3562 /* Bind the saved DEVMODE to the new the printer */
3564 free_nt_devicemode(&info_ptr
->devmode
);
3565 info_ptr
->devmode
= info
.devmode
;
3567 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3568 info_ptr
->printername
, info_ptr
->devmode
?"VALID":"NULL", info_ptr
->drivername
));
3570 /* Add the printer data 'values' to the new printer */
3572 len
+= unpack_values( &info_ptr
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3575 SAFE_FREE(dbuf
.dptr
);
3580 /****************************************************************************
3581 Initialize printer devmode & data with previously saved driver init values.
3582 When a printer is created using AddPrinter, the drivername bound to the
3583 printer is used to lookup previously saved driver initialization info, which
3584 is bound to the new printer.
3585 ****************************************************************************/
3587 BOOL
set_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3589 BOOL result
= False
;
3593 result
= set_driver_init_2(printer
->info_2
);
3597 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3605 /****************************************************************************
3606 Delete driver init data stored for a specified driver
3607 ****************************************************************************/
3609 BOOL
del_driver_init(char *drivername
)
3614 if (!drivername
|| !*drivername
) {
3615 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3619 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, drivername
);
3622 kbuf
.dsize
= strlen(key
)+1;
3624 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername
));
3626 return (tdb_delete(tdb_drivers
, kbuf
) == 0);
3629 /****************************************************************************
3630 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3631 in the tdb. Note: this is different from the driver entry and the printer
3632 entry. There should be a single driver init entry for each driver regardless
3633 of whether it was installed from NT or 2K. Technically, they should be
3634 different, but they work out to the same struct.
3635 ****************************************************************************/
3637 static uint32
update_driver_init_2(NT_PRINTER_INFO_LEVEL_2
*info
)
3641 int buflen
, len
, ret
;
3642 TDB_DATA kbuf
, dbuf
;
3649 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
3651 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
3653 if (buflen
!= len
) {
3656 tb
= (char *)Realloc(buf
, len
);
3658 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3668 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info
->drivername
);
3671 kbuf
.dsize
= strlen(key
)+1;
3675 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
3679 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3683 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3684 info
->sharename
, info
->drivername
));
3689 /****************************************************************************
3690 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3691 ****************************************************************************/
3693 uint32
update_driver_init(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
3697 dump_a_printer(printer
, level
);
3701 result
= update_driver_init_2(printer
.info_2
);
3711 /****************************************************************************
3712 Convert the printer data value, a REG_BINARY array, into an initialization
3713 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3714 got to keep the endians happy :).
3715 ****************************************************************************/
3717 static BOOL
convert_driver_init( TALLOC_CTX
*ctx
, NT_DEVICEMODE
*nt_devmode
, uint8
*data
, uint32 data_len
)
3719 BOOL result
= False
;
3723 ZERO_STRUCT(devmode
);
3725 prs_init(&ps
, 0, ctx
, UNMARSHALL
);
3726 ps
.data_p
= (char *)data
;
3727 ps
.buffer_size
= data_len
;
3729 if (spoolss_io_devmode("phantom DEVMODE", &ps
, 0, &devmode
))
3730 result
= convert_devicemode("", &devmode
, &nt_devmode
);
3732 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3737 /****************************************************************************
3738 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3740 1. Use the driver's config DLL to this UNC printername and:
3741 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3742 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3743 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3745 The last step triggers saving the "driver initialization" information for
3746 this printer into the tdb. Later, new printers that use this driver will
3747 have this initialization information bound to them. This simulates the
3748 driver initialization, as if it had run on the Samba server (as it would
3751 The Win32 client side code requirement sucks! But until we can run arbitrary
3752 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3754 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3755 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3756 about it and you will realize why. JRR 010720
3757 ****************************************************************************/
3759 static WERROR
save_driver_init_2(NT_PRINTER_INFO_LEVEL
*printer
, uint8
*data
, uint32 data_len
)
3761 WERROR status
= WERR_OK
;
3762 TALLOC_CTX
*ctx
= NULL
;
3763 NT_DEVICEMODE
*nt_devmode
= NULL
;
3764 NT_DEVICEMODE
*tmp_devmode
= printer
->info_2
->devmode
;
3767 * When the DEVMODE is already set on the printer, don't try to unpack it.
3769 DEBUG(8,("save_driver_init_2: Enter...\n"));
3771 if ( !printer
->info_2
->devmode
&& data_len
) {
3773 * Set devmode on printer info, so entire printer initialization can be
3777 if ((ctx
= talloc_init("save_driver_init_2")) == NULL
)
3780 if ((nt_devmode
= (NT_DEVICEMODE
*)malloc(sizeof(NT_DEVICEMODE
))) == NULL
) {
3781 status
= WERR_NOMEM
;
3785 ZERO_STRUCTP(nt_devmode
);
3788 * The DEVMODE is held in the 'data' component of the param in raw binary.
3789 * Convert it to to a devmode structure
3791 if ( !convert_driver_init( ctx
, nt_devmode
, data
, data_len
)) {
3792 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3793 status
= WERR_INVALID_PARAM
;
3797 printer
->info_2
->devmode
= nt_devmode
;
3801 * Pack up and add (or update) the DEVMODE and any current printer data to
3802 * a 'driver init' element in the tdb
3806 if ( update_driver_init(*printer
, 2) != 0 ) {
3807 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3808 status
= WERR_NOMEM
;
3813 * If driver initialization info was successfully saved, set the current
3814 * printer to match it. This allows initialization of the current printer
3815 * as well as the driver.
3817 status
= mod_a_printer(*printer
, 2);
3818 if (!W_ERROR_IS_OK(status
)) {
3819 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3820 printer
->info_2
->printername
));
3824 talloc_destroy(ctx
);
3825 free_nt_devicemode( &nt_devmode
);
3827 printer
->info_2
->devmode
= tmp_devmode
;
3832 /****************************************************************************
3833 Update the driver init info (DEVMODE and specifics) for a printer
3834 ****************************************************************************/
3836 WERROR
save_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
, uint8
*data
, uint32 data_len
)
3838 WERROR status
= WERR_OK
;
3842 status
= save_driver_init_2( printer
, data
, data_len
);
3845 status
= WERR_UNKNOWN_LEVEL
;
3852 /****************************************************************************
3853 Deep copy a NT_PRINTER_DATA
3854 ****************************************************************************/
3856 static NTSTATUS
copy_printer_data( NT_PRINTER_DATA
*dst
, NT_PRINTER_DATA
*src
)
3858 int i
, j
, num_vals
, new_key_index
;
3859 REGVAL_CTR
*src_key
, *dst_key
;
3862 return NT_STATUS_NO_MEMORY
;
3864 for ( i
=0; i
<src
->num_keys
; i
++ ) {
3866 /* create a new instance of the printerkey in the destination
3867 printer_data object */
3869 new_key_index
= add_new_printer_key( dst
, src
->keys
[i
].name
);
3870 dst_key
= &dst
->keys
[new_key_index
].values
;
3872 src_key
= &src
->keys
[i
].values
;
3873 num_vals
= regval_ctr_numvals( src_key
);
3875 /* dup the printer entire printer key */
3877 for ( j
=0; j
<num_vals
; j
++ ) {
3878 regval_ctr_copyvalue( dst_key
, regval_ctr_specific_value(src_key
, j
) );
3882 return NT_STATUS_OK
;
3885 /****************************************************************************
3886 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
3888 ****************************************************************************/
3890 NT_PRINTER_INFO_LEVEL_2
* dup_printer_2( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL_2
*printer
)
3892 NT_PRINTER_INFO_LEVEL_2
*copy
;
3897 if ( !(copy
= (NT_PRINTER_INFO_LEVEL_2
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2
))) )
3900 memcpy( copy
, printer
, sizeof(NT_PRINTER_INFO_LEVEL_2
) );
3902 /* malloc()'d members copied here */
3904 copy
->devmode
= dup_nt_devicemode( printer
->devmode
);
3906 ZERO_STRUCT( copy
->data
);
3907 copy_printer_data( ©
->data
, &printer
->data
);
3909 /* this is talloc()'d; very ugly that we have a structure that
3910 is half malloc()'d and half talloc()'d but that is the way
3911 that the PRINTER_INFO stuff is written right now. --jerry */
3913 copy
->secdesc_buf
= dup_sec_desc_buf( ctx
, printer
->secdesc_buf
);
3918 /****************************************************************************
3919 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3921 Previously the code had a memory allocation problem because it always
3922 used the TALLOC_CTX from the Printer_entry*. This context lasts
3923 as a long as the original handle is open. So if the client made a lot
3924 of getprinter[data]() calls, the memory usage would climb. Now we use
3925 a short lived TALLOC_CTX for printer_info_2 objects returned. We
3926 still use the Printer_entry->ctx for maintaining the cache copy though
3927 since that object must live as long as the handle by definition.
3930 ****************************************************************************/
3932 WERROR
get_a_printer( Printer_entry
*print_hnd
, NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
,
3933 const char *sharename
)
3936 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3940 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename
, (unsigned int)level
));
3944 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
3945 DEBUG(0,("get_a_printer: malloc fail.\n"));
3948 ZERO_STRUCTP(printer
);
3951 * check for cache first. A Printer handle cannot changed
3952 * to another printer object so we only check that the printer
3953 * is actually for a printer and that the printer_info pointer
3957 && (print_hnd
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)
3958 && print_hnd
->printer_info
)
3960 /* get_talloc_ctx() works here because we need a short
3961 lived talloc context */
3963 if ( !(printer
->info_2
= dup_printer_2(get_talloc_ctx(), print_hnd
->printer_info
->info_2
)) )
3965 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
3971 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
3973 *pp_printer
= printer
;
3979 /* no cache for this handle; see if we can match one from another handle.
3980 Make sure to use a short lived talloc ctx */
3983 result
= find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer
->info_2
, sharename
);
3985 /* fail to disk if we don't have it with any open handle */
3987 if ( !print_hnd
|| !W_ERROR_IS_OK(result
) )
3988 result
= get_a_printer_2(&printer
->info_2
, sharename
);
3990 /* we have a new printer now. Save it with this handle */
3992 if ( W_ERROR_IS_OK(result
) ) {
3993 dump_a_printer(*printer
, level
);
3995 /* save a copy in cache */
3996 if ( print_hnd
&& (print_hnd
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)) {
3997 if ( !print_hnd
->printer_info
)
3998 print_hnd
->printer_info
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
));
4000 if ( print_hnd
->printer_info
) {
4001 /* make sure to use the handle's talloc ctx here since
4002 the printer_2 object must last until the handle is closed */
4004 print_hnd
->printer_info
->info_2
= dup_printer_2(print_hnd
->ctx
, printer
->info_2
);
4006 /* don't fail the lookup just because the cache update failed */
4007 if ( !print_hnd
->printer_info
->info_2
)
4008 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4011 *pp_printer
= printer
;
4019 result
=WERR_UNKNOWN_LEVEL
;
4023 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename
, (unsigned int)level
, dos_errstr(result
)));
4028 /****************************************************************************
4029 Deletes a NT_PRINTER_INFO_LEVEL struct.
4030 ****************************************************************************/
4032 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
4035 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
4037 DEBUG(104,("freeing a printer at level [%d]\n", level
));
4039 if (printer
== NULL
)
4044 if (printer
->info_2
!= NULL
) {
4045 free_nt_printer_info_level_2(&printer
->info_2
);
4056 SAFE_FREE(*pp_printer
);
4060 /****************************************************************************
4061 ****************************************************************************/
4062 uint32
add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4065 DEBUG(104,("adding a printer at level [%d]\n", level
));
4066 dump_a_printer_driver(driver
, level
);
4070 result
=add_a_printer_driver_3(driver
.info_3
);
4074 result
=add_a_printer_driver_6(driver
.info_6
);
4084 /****************************************************************************
4085 ****************************************************************************/
4087 WERROR
get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL
*driver
, uint32 level
,
4088 fstring drivername
, const char *architecture
, uint32 version
)
4094 /* Sometime we just want any version of the driver */
4096 if ( version
== DRIVER_ANY_VERSION
) {
4097 /* look for Win2k first and then for NT4 */
4098 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4101 if ( !W_ERROR_IS_OK(result
) ) {
4102 result
= get_a_printer_driver_3( &driver
->info_3
,
4103 drivername
, architecture
, 2 );
4106 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4107 architecture
, version
);
4116 if (W_ERROR_IS_OK(result
))
4117 dump_a_printer_driver(*driver
, level
);
4122 /****************************************************************************
4123 ****************************************************************************/
4124 uint32
free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4131 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
4132 if (driver
.info_3
!= NULL
)
4134 info3
=driver
.info_3
;
4135 SAFE_FREE(info3
->dependentfiles
);
4136 ZERO_STRUCTP(info3
);
4146 NT_PRINTER_DRIVER_INFO_LEVEL_6
*info6
;
4147 if (driver
.info_6
!= NULL
) {
4148 info6
=driver
.info_6
;
4149 SAFE_FREE(info6
->dependentfiles
);
4150 SAFE_FREE(info6
->previousnames
);
4151 ZERO_STRUCTP(info6
);
4167 /****************************************************************************
4168 Determine whether or not a particular driver is currently assigned
4170 ****************************************************************************/
4172 BOOL
printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
)
4175 int n_services
= lp_numservices();
4176 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4181 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4183 /* loop through the printers.tdb and check for the drivername */
4185 for (snum
=0; snum
<n_services
; snum
++) {
4186 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
4189 if ( !W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))) )
4192 if ( !StrCaseCmp(info_3
->name
, printer
->info_2
->drivername
) ) {
4193 free_a_printer( &printer
, 2 );
4197 free_a_printer( &printer
, 2 );
4200 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4202 /* report that the driver is not in use by default */
4208 /**********************************************************************
4209 Check to see if a ogiven file is in use by *info
4210 *********************************************************************/
4212 static BOOL
drv_file_in_use( char* file
, NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4219 if ( strequal(file
, info
->driverpath
) )
4222 if ( strequal(file
, info
->datafile
) )
4225 if ( strequal(file
, info
->configfile
) )
4228 if ( strequal(file
, info
->helpfile
) )
4231 /* see of there are any dependent files to examine */
4233 if ( !info
->dependentfiles
)
4236 while ( *info
->dependentfiles
[i
] ) {
4237 if ( strequal(file
, info
->dependentfiles
[i
]) )
4246 /**********************************************************************
4247 Utility function to remove the dependent file pointed to by the
4248 input parameter from the list
4249 *********************************************************************/
4251 static void trim_dependent_file( fstring files
[], int idx
)
4254 /* bump everything down a slot */
4256 while( *files
[idx
+1] ) {
4257 fstrcpy( files
[idx
], files
[idx
+1] );
4266 /**********************************************************************
4267 Check if any of the files used by src are also used by drv
4268 *********************************************************************/
4270 static BOOL
trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*src
,
4271 NT_PRINTER_DRIVER_INFO_LEVEL_3
*drv
)
4273 BOOL in_use
= False
;
4279 /* check each file. Remove it from the src structure if it overlaps */
4281 if ( drv_file_in_use(src
->driverpath
, drv
) ) {
4283 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driverpath
));
4284 fstrcpy( src
->driverpath
, "" );
4287 if ( drv_file_in_use(src
->datafile
, drv
) ) {
4289 DEBUG(10,("Removing datafile [%s] from list\n", src
->datafile
));
4290 fstrcpy( src
->datafile
, "" );
4293 if ( drv_file_in_use(src
->configfile
, drv
) ) {
4295 DEBUG(10,("Removing configfile [%s] from list\n", src
->configfile
));
4296 fstrcpy( src
->configfile
, "" );
4299 if ( drv_file_in_use(src
->helpfile
, drv
) ) {
4301 DEBUG(10,("Removing helpfile [%s] from list\n", src
->helpfile
));
4302 fstrcpy( src
->helpfile
, "" );
4305 /* are there any dependentfiles to examine? */
4307 if ( !src
->dependentfiles
)
4310 while ( *src
->dependentfiles
[i
] ) {
4311 if ( drv_file_in_use(src
->dependentfiles
[i
], drv
) ) {
4313 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependentfiles
[i
]));
4314 trim_dependent_file( src
->dependentfiles
, i
);
4322 /****************************************************************************
4323 Determine whether or not a particular driver files are currently being
4324 used by any other driver.
4326 Return value is True if any files were in use by other drivers
4327 and False otherwise.
4329 Upon return, *info has been modified to only contain the driver files
4330 which are not in use
4331 ****************************************************************************/
4333 BOOL
printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4338 fstring
*list
= NULL
;
4339 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4344 version
= info
->cversion
;
4346 /* loop over all driver versions */
4348 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4350 /* get the list of drivers */
4353 ndrivers
= get_ntdrivers(&list
, info
->environment
, version
);
4355 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4356 ndrivers
, info
->environment
, version
));
4358 /* check each driver for overlap in files */
4360 for (i
=0; i
<ndrivers
; i
++) {
4361 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
4363 ZERO_STRUCT(driver
);
4365 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, list
[i
], info
->environment
, version
)) ) {
4370 /* check if d2 uses any files from d1 */
4371 /* only if this is a different driver than the one being deleted */
4373 if ( !strequal(info
->name
, driver
.info_3
->name
) ) {
4374 if ( trim_overlap_drv_files(info
, driver
.info_3
) ) {
4375 free_a_printer_driver(driver
, 3);
4381 free_a_printer_driver(driver
, 3);
4386 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4388 driver
.info_3
= info
;
4390 if ( DEBUGLEVEL
>= 20 )
4391 dump_a_printer_driver( driver
, 3 );
4396 /****************************************************************************
4397 Actually delete the driver files. Make sure that
4398 printer_driver_files_in_use() return False before calling
4400 ****************************************************************************/
4402 static BOOL
delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
)
4406 connection_struct
*conn
;
4414 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3
->name
, info_3
->cversion
));
4417 * Connect to the print$ share under the same account as the
4418 * user connected to the rpc pipe. Note we must be root to
4422 null_pw
= data_blob( NULL
, 0 );
4423 fstrcpy(res_type
, "A:");
4425 conn
= make_connection_with_chdir( "print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
4429 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4433 /* Save who we are - we are temporarily becoming the connection user. */
4435 if ( !become_user(conn
, conn
->vuid
) ) {
4436 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4440 /* now delete the files; must strip the '\print$' string from
4443 if ( *info_3
->driverpath
) {
4444 if ( (s
= strchr( &info_3
->driverpath
[1], '\\' )) != NULL
) {
4445 DEBUG(10,("deleting driverfile [%s]\n", s
));
4446 unlink_internals(conn
, 0, s
);
4450 if ( *info_3
->configfile
) {
4451 if ( (s
= strchr( &info_3
->configfile
[1], '\\' )) != NULL
) {
4452 DEBUG(10,("deleting configfile [%s]\n", s
));
4453 unlink_internals(conn
, 0, s
);
4457 if ( *info_3
->datafile
) {
4458 if ( (s
= strchr( &info_3
->datafile
[1], '\\' )) != NULL
) {
4459 DEBUG(10,("deleting datafile [%s]\n", s
));
4460 unlink_internals(conn
, 0, s
);
4464 if ( *info_3
->helpfile
) {
4465 if ( (s
= strchr( &info_3
->helpfile
[1], '\\' )) != NULL
) {
4466 DEBUG(10,("deleting helpfile [%s]\n", s
));
4467 unlink_internals(conn
, 0, s
);
4471 /* check if we are done removing files */
4473 if ( info_3
->dependentfiles
) {
4474 while ( *info_3
->dependentfiles
[i
] ) {
4477 /* bypass the "\print$" portion of the path */
4479 if ( (file
= strchr( info_3
->dependentfiles
[i
]+1, '\\' )) != NULL
) {
4480 DEBUG(10,("deleting dependent file [%s]\n", file
));
4481 unlink_internals(conn
, 0, file
);
4493 /****************************************************************************
4494 Remove a printer driver from the TDB. This assumes that the the driver was
4495 previously looked up.
4496 ***************************************************************************/
4498 WERROR
delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
,
4499 uint32 version
, BOOL delete_files
)
4503 TDB_DATA kbuf
, dbuf
;
4504 NT_PRINTER_DRIVER_INFO_LEVEL ctr
;
4506 /* delete the tdb data first */
4508 arch
= get_short_archi(info_3
->environment
);
4509 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
,
4510 arch
, version
, info_3
->name
);
4512 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4513 key
, delete_files
? "TRUE" : "FALSE" ));
4515 ctr
.info_3
= info_3
;
4516 dump_a_printer_driver( ctr
, 3 );
4519 kbuf
.dsize
=strlen(key
)+1;
4521 /* check if the driver actually exists for this environment */
4523 dbuf
= tdb_fetch( tdb_drivers
, kbuf
);
4525 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key
));
4526 return WERR_UNKNOWN_PRINTER_DRIVER
;
4529 SAFE_FREE( dbuf
.dptr
);
4531 /* ok... the driver exists so the delete should return success */
4533 if (tdb_delete(tdb_drivers
, kbuf
) == -1) {
4534 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key
));
4535 return WERR_ACCESS_DENIED
;
4539 * now delete any associated files if delete_files == True
4540 * even if this part failes, we return succes because the
4541 * driver doesn not exist any more
4545 delete_driver_files( info_3
, user
);
4548 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key
));
4553 /****************************************************************************
4554 Store a security desc for a printer.
4555 ****************************************************************************/
4557 WERROR
nt_printing_setsec(const char *printername
, SEC_DESC_BUF
*secdesc_ctr
)
4559 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4560 SEC_DESC_BUF
*old_secdesc_ctr
= NULL
;
4562 TALLOC_CTX
*mem_ctx
= NULL
;
4566 mem_ctx
= talloc_init("nt_printing_setsec");
4567 if (mem_ctx
== NULL
)
4570 /* The old owner and group sids of the security descriptor are not
4571 present when new ACEs are added or removed by changing printer
4572 permissions through NT. If they are NULL in the new security
4573 descriptor then copy them over from the old one. */
4575 if (!secdesc_ctr
->sec
->owner_sid
|| !secdesc_ctr
->sec
->grp_sid
) {
4576 DOM_SID
*owner_sid
, *group_sid
;
4577 SEC_ACL
*dacl
, *sacl
;
4578 SEC_DESC
*psd
= NULL
;
4581 nt_printing_getsec(mem_ctx
, printername
, &old_secdesc_ctr
);
4583 /* Pick out correct owner and group sids */
4585 owner_sid
= secdesc_ctr
->sec
->owner_sid
?
4586 secdesc_ctr
->sec
->owner_sid
:
4587 old_secdesc_ctr
->sec
->owner_sid
;
4589 group_sid
= secdesc_ctr
->sec
->grp_sid
?
4590 secdesc_ctr
->sec
->grp_sid
:
4591 old_secdesc_ctr
->sec
->grp_sid
;
4593 dacl
= secdesc_ctr
->sec
->dacl
?
4594 secdesc_ctr
->sec
->dacl
:
4595 old_secdesc_ctr
->sec
->dacl
;
4597 sacl
= secdesc_ctr
->sec
->sacl
?
4598 secdesc_ctr
->sec
->sacl
:
4599 old_secdesc_ctr
->sec
->sacl
;
4601 /* Make a deep copy of the security descriptor */
4603 psd
= make_sec_desc(mem_ctx
, secdesc_ctr
->sec
->revision
, secdesc_ctr
->sec
->type
,
4604 owner_sid
, group_sid
,
4609 new_secdesc_ctr
= make_sec_desc_buf(mem_ctx
, size
, psd
);
4612 if (!new_secdesc_ctr
) {
4613 new_secdesc_ctr
= secdesc_ctr
;
4616 /* Store the security descriptor in a tdb */
4618 prs_init(&ps
, (uint32
)sec_desc_size(new_secdesc_ctr
->sec
) +
4619 sizeof(SEC_DESC_BUF
), mem_ctx
, MARSHALL
);
4621 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr
,
4623 status
= WERR_BADFUNC
;
4627 slprintf(key
, sizeof(key
)-1, "SECDESC/%s", printername
);
4629 if (tdb_prs_store(tdb_printers
, key
, &ps
)==0) {
4632 DEBUG(1,("Failed to store secdesc for %s\n", printername
));
4633 status
= WERR_BADFUNC
;
4636 /* Free malloc'ed memory */
4642 talloc_destroy(mem_ctx
);
4646 /****************************************************************************
4647 Construct a default security descriptor buffer for a printer.
4648 ****************************************************************************/
4650 static SEC_DESC_BUF
*construct_default_printer_sdb(TALLOC_CTX
*ctx
)
4654 SEC_ACL
*psa
= NULL
;
4655 SEC_DESC_BUF
*sdb
= NULL
;
4656 SEC_DESC
*psd
= NULL
;
4660 /* Create an ACE where Everyone is allowed to print */
4662 init_sec_access(&sa
, PRINTER_ACE_PRINT
);
4663 init_sec_ace(&ace
[0], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4664 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4666 /* Make the security descriptor owned by the Administrators group
4667 on the PDC of the domain. */
4669 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
4670 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4673 /* Backup plan - make printer owned by admins.
4674 This should emulate a lanman printer as security
4675 settings can't be changed. */
4677 sid_copy(&owner_sid
, get_global_sam_sid());
4678 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4681 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
4682 init_sec_ace(&ace
[1], &owner_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4683 sa
, SEC_ACE_FLAG_OBJECT_INHERIT
|
4684 SEC_ACE_FLAG_INHERIT_ONLY
);
4686 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
4687 init_sec_ace(&ace
[2], &owner_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4688 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4690 /* The ACL revision number in rpc_secdesc.h differs from the one
4691 created by NT when setting ACE entries in printer
4692 descriptors. NT4 complains about the property being edited by a
4695 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, 3, ace
)) != NULL
) {
4696 psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
4698 NULL
, psa
, &sd_size
);
4702 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4706 sdb
= make_sec_desc_buf(ctx
, sd_size
, psd
);
4708 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4709 (unsigned int)sd_size
));
4714 /****************************************************************************
4715 Get a security desc for a printer.
4716 ****************************************************************************/
4718 BOOL
nt_printing_getsec(TALLOC_CTX
*ctx
, const char *printername
, SEC_DESC_BUF
**secdesc_ctr
)
4724 if (strlen(printername
) > 2 && (temp
= strchr(printername
+ 2, '\\'))) {
4725 printername
= temp
+ 1;
4728 /* Fetch security descriptor from tdb */
4730 slprintf(key
, sizeof(key
)-1, "SECDESC/%s", printername
);
4732 if (tdb_prs_fetch(tdb_printers
, key
, &ps
, ctx
)!=0 ||
4733 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1)) {
4735 DEBUG(4,("using default secdesc for %s\n", printername
));
4737 if (!(*secdesc_ctr
= construct_default_printer_sdb(ctx
))) {
4741 /* Save default security descriptor for later */
4743 prs_init(&ps
, (uint32
)sec_desc_size((*secdesc_ctr
)->sec
) +
4744 sizeof(SEC_DESC_BUF
), ctx
, MARSHALL
);
4746 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1))
4747 tdb_prs_store(tdb_printers
, key
, &ps
);
4754 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4755 this security descriptor has been created when winbindd was
4756 down. Take ownership of security descriptor. */
4758 if (sid_equal((*secdesc_ctr
)->sec
->owner_sid
, &global_sid_World
)) {
4761 /* Change sd owner to workgroup administrator */
4763 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
4764 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4765 SEC_DESC
*psd
= NULL
;
4770 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4772 psd
= make_sec_desc(ctx
, (*secdesc_ctr
)->sec
->revision
, (*secdesc_ctr
)->sec
->type
,
4774 (*secdesc_ctr
)->sec
->grp_sid
,
4775 (*secdesc_ctr
)->sec
->sacl
,
4776 (*secdesc_ctr
)->sec
->dacl
,
4779 new_secdesc_ctr
= make_sec_desc_buf(ctx
, size
, psd
);
4781 /* Swap with other one */
4783 *secdesc_ctr
= new_secdesc_ctr
;
4787 nt_printing_setsec(printername
, *secdesc_ctr
);
4791 if (DEBUGLEVEL
>= 10) {
4792 SEC_ACL
*the_acl
= (*secdesc_ctr
)->sec
->dacl
;
4795 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4796 printername
, the_acl
->num_aces
));
4798 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4801 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
4803 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str
,
4804 the_acl
->ace
[i
].type
, the_acl
->ace
[i
].flags
,
4805 the_acl
->ace
[i
].info
.mask
));
4815 1: level not implemented
4816 2: file doesn't exist
4817 3: can't allocate memory
4818 4: can't free memory
4819 5: non existant struct
4823 A printer and a printer driver are 2 different things.
4824 NT manages them separatelly, Samba does the same.
4825 Why ? Simply because it's easier and it makes sense !
4827 Now explanation: You have 3 printers behind your samba server,
4828 2 of them are the same make and model (laser A and B). But laser B
4829 has an 3000 sheet feeder and laser A doesn't such an option.
4830 Your third printer is an old dot-matrix model for the accounting :-).
4832 If the /usr/local/samba/lib directory (default dir), you will have
4833 5 files to describe all of this.
4835 3 files for the printers (1 by printer):
4838 NTprinter_accounting
4839 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4840 NTdriver_printer model X
4841 NTdriver_printer model Y
4843 jfm: I should use this comment for the text file to explain
4844 same thing for the forms BTW.
4845 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4849 /* Convert generic access rights to printer object specific access rights.
4850 It turns out that NT4 security descriptors use generic access rights and
4851 NT5 the object specific ones. */
4853 void map_printer_permissions(SEC_DESC
*sd
)
4857 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
4858 se_map_generic(&sd
->dacl
->ace
[i
].info
.mask
,
4859 &printer_generic_mapping
);
4863 /****************************************************************************
4864 Check a user has permissions to perform the given operation. We use the
4865 permission constants defined in include/rpc_spoolss.h to check the various
4866 actions we perform when checking printer access.
4868 PRINTER_ACCESS_ADMINISTER:
4869 print_queue_pause, print_queue_resume, update_printer_sec,
4870 update_printer, spoolss_addprinterex_level_2,
4871 _spoolss_setprinterdata
4876 JOB_ACCESS_ADMINISTER:
4877 print_job_delete, print_job_pause, print_job_resume,
4880 ****************************************************************************/
4881 BOOL
print_access_check(struct current_user
*user
, int snum
, int access_type
)
4883 SEC_DESC_BUF
*secdesc
= NULL
;
4884 uint32 access_granted
;
4888 TALLOC_CTX
*mem_ctx
= NULL
;
4889 extern struct current_user current_user
;
4891 /* If user is NULL then use the current_user structure */
4894 user
= ¤t_user
;
4896 /* Always allow root or printer admins to do anything */
4898 if (user
->uid
== 0 ||
4899 user_in_list(uidtoname(user
->uid
), lp_printer_admin(snum
), user
->groups
, user
->ngroups
)) {
4903 /* Get printer name */
4905 pname
= PRINTERNAME(snum
);
4907 if (!pname
|| !*pname
) {
4912 /* Get printer security descriptor */
4914 if(!(mem_ctx
= talloc_init("print_access_check"))) {
4919 nt_printing_getsec(mem_ctx
, pname
, &secdesc
);
4921 if (access_type
== JOB_ACCESS_ADMINISTER
) {
4922 SEC_DESC_BUF
*parent_secdesc
= secdesc
;
4924 /* Create a child security descriptor to check permissions
4925 against. This is because print jobs are child objects
4926 objects of a printer. */
4928 secdesc
= se_create_child_secdesc(mem_ctx
, parent_secdesc
->sec
, False
);
4930 /* Now this is the bit that really confuses me. The access
4931 type needs to be changed from JOB_ACCESS_ADMINISTER to
4932 PRINTER_ACCESS_ADMINISTER for this to work. Something
4933 to do with the child (job) object becoming like a
4936 access_type
= PRINTER_ACCESS_ADMINISTER
;
4941 map_printer_permissions(secdesc
->sec
);
4943 result
= se_access_check(secdesc
->sec
, user
->nt_user_token
, access_type
,
4944 &access_granted
, &status
);
4946 DEBUG(4, ("access check was %s\n", result
? "SUCCESS" : "FAILURE"));
4948 talloc_destroy(mem_ctx
);
4956 /****************************************************************************
4957 Check the time parameters allow a print operation.
4958 *****************************************************************************/
4960 BOOL
print_time_access_check(int snum
)
4962 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4964 time_t now
= time(NULL
);
4968 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))))
4971 if (printer
->info_2
->starttime
== 0 && printer
->info_2
->untiltime
== 0)
4975 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
4977 if (mins
>= printer
->info_2
->starttime
&& mins
<= printer
->info_2
->untiltime
)
4980 free_a_printer(&printer
, 2);