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"
212 #define SPL_ARCH_IA64 "IA64"
213 #define SPL_ARCH_X64 "x64"
215 static const struct table_node archi_table
[]= {
217 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
218 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
219 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
220 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
221 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
222 {"Windows IA64", SPL_ARCH_IA64
, 3 },
223 {"Windows x64", SPL_ARCH_X64
, 3 },
227 static BOOL
upgrade_to_version_3(void)
229 TDB_DATA kbuf
, newkey
, dbuf
;
231 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
233 for (kbuf
= tdb_firstkey(tdb_drivers
); kbuf
.dptr
;
234 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
236 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
238 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) == 0) {
239 DEBUG(0,("upgrade_to_version_3:moving form\n"));
240 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
241 SAFE_FREE(dbuf
.dptr
);
242 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms
)));
245 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
246 SAFE_FREE(dbuf
.dptr
);
247 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
252 if (strncmp(kbuf
.dptr
, PRINTERS_PREFIX
, strlen(PRINTERS_PREFIX
)) == 0) {
253 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
254 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
255 SAFE_FREE(dbuf
.dptr
);
256 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers
)));
259 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
260 SAFE_FREE(dbuf
.dptr
);
261 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
266 if (strncmp(kbuf
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
)) == 0) {
267 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
268 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
269 SAFE_FREE(dbuf
.dptr
);
270 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers
)));
273 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
274 SAFE_FREE(dbuf
.dptr
);
275 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
280 SAFE_FREE(dbuf
.dptr
);
286 /****************************************************************************
287 Open the NT printing tdbs. Done once before fork().
288 ****************************************************************************/
290 BOOL
nt_printing_init(void)
292 static pid_t local_pid
;
293 const char *vstring
= "INFO/version";
296 if (tdb_drivers
&& tdb_printers
&& tdb_forms
&& local_pid
== sys_getpid())
300 tdb_close(tdb_drivers
);
301 tdb_drivers
= tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
303 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
304 lock_path("ntdrivers.tdb"), strerror(errno
) ));
309 tdb_close(tdb_printers
);
310 tdb_printers
= tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
312 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
313 lock_path("ntprinters.tdb"), strerror(errno
) ));
318 tdb_close(tdb_forms
);
319 tdb_forms
= tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
321 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
322 lock_path("ntforms.tdb"), strerror(errno
) ));
326 local_pid
= sys_getpid();
328 /* handle a Samba upgrade */
329 tdb_lock_bystring(tdb_drivers
, vstring
, 0);
333 /* Cope with byte-reversed older versions of the db. */
334 vers_id
= tdb_fetch_int32(tdb_drivers
, vstring
);
335 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_2
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_2
)) {
336 /* Written on a bigendian machine with old fetch_int code. Save as le. */
337 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
338 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION
);
339 vers_id
= NTDRIVERS_DATABASE_VERSION
;
342 if (vers_id
!= NTDRIVERS_DATABASE_VERSION
) {
344 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_1
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_1
)) {
345 if (!upgrade_to_version_3())
348 tdb_traverse(tdb_drivers
, tdb_traverse_delete_fn
, NULL
);
350 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION
);
353 tdb_unlock_bystring(tdb_drivers
, vstring
);
355 update_c_setprinter(True
);
358 * register callback to handle updating printers as new
359 * drivers are installed
362 message_register( MSG_PRINTER_DRVUPGRADE
, do_drv_upgrade_printer
);
365 * register callback to handle updating printer data
366 * when a driver is initialized
369 message_register( MSG_PRINTERDATA_INIT_RESET
, reset_all_printerdata
);
372 * register callback to handle invalidating the printer cache
373 * between smbd processes.
376 message_register( MSG_PRINTER_MOD
, receive_printer_mod_msg
);
378 /* of course, none of the message callbacks matter if you don't
379 tell messages.c that you interested in receiving PRINT_GENERAL
380 msgs. This is done in claim_connection() */
383 if ( lp_security() == SEC_ADS
) {
384 win_rc
= check_published_printers();
385 if (!W_ERROR_IS_OK(win_rc
))
386 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc
)));
392 /*******************************************************************
393 Function to allow filename parsing "the old way".
394 ********************************************************************/
396 static BOOL
driver_unix_convert(char *name
,connection_struct
*conn
,
397 char *saved_last_component
, BOOL
*bad_path
, SMB_STRUCT_STAT
*pst
)
400 unix_clean_name(name
);
401 trim_string(name
,"/","/");
402 return unix_convert(name
, conn
, saved_last_component
, bad_path
, pst
);
405 /*******************************************************************
406 tdb traversal function for counting printers.
407 ********************************************************************/
409 static int traverse_counting_printers(TDB_CONTEXT
*t
, TDB_DATA key
,
410 TDB_DATA data
, void *context
)
412 int *printer_count
= (int*)context
;
414 if (memcmp(PRINTERS_PREFIX
, key
.dptr
, sizeof(PRINTERS_PREFIX
)-1) == 0) {
416 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key
.dptr
, *printer_count
));
422 /*******************************************************************
423 Update the spooler global c_setprinter. This variable is initialized
424 when the parent smbd starts with the number of existing printers. It
425 is monotonically increased by the current number of printers *after*
426 each add or delete printer RPC. Only Microsoft knows why... JRR020119
427 ********************************************************************/
429 uint32
update_c_setprinter(BOOL initialize
)
432 int32 printer_count
= 0;
434 tdb_lock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
, 0);
436 /* Traverse the tdb, counting the printers */
437 tdb_traverse(tdb_printers
, traverse_counting_printers
, (void *)&printer_count
);
439 /* If initializing, set c_setprinter to current printers count
440 * otherwise, bump it by the current printer count
443 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
) + printer_count
;
445 c_setprinter
= printer_count
;
447 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter
));
448 tdb_store_int32(tdb_printers
, GLOBAL_C_SETPRINTER
, c_setprinter
);
450 tdb_unlock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
452 return (uint32
)c_setprinter
;
455 /*******************************************************************
456 Get the spooler global c_setprinter, accounting for initialization.
457 ********************************************************************/
459 uint32
get_c_setprinter(void)
461 int32 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
);
463 if (c_setprinter
== (int32
)-1)
464 c_setprinter
= update_c_setprinter(True
);
466 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter
));
468 return (uint32
)c_setprinter
;
471 /****************************************************************************
472 Get builtin form struct list.
473 ****************************************************************************/
475 int get_builtin_ntforms(nt_forms_struct
**list
)
477 *list
= (nt_forms_struct
*)memdup(&default_forms
[0], sizeof(default_forms
));
478 return sizeof(default_forms
) / sizeof(default_forms
[0]);
481 /****************************************************************************
482 get a builtin form struct
483 ****************************************************************************/
485 BOOL
get_a_builtin_ntform(UNISTR2
*uni_formname
,nt_forms_struct
*form
)
489 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
490 DEBUGADD(6,("Looking for builtin form %s \n", form_name
));
491 count
= sizeof(default_forms
) / sizeof(default_forms
[0]);
492 for (i
=0;i
<count
;i
++) {
493 if (strequal(form_name
,default_forms
[i
].name
)) {
494 DEBUGADD(6,("Found builtin form %s \n", form_name
));
495 memcpy(form
,&default_forms
[i
],sizeof(*form
));
503 /****************************************************************************
504 get a form struct list
505 ****************************************************************************/
506 int get_ntforms(nt_forms_struct
**list
)
508 TDB_DATA kbuf
, newkey
, dbuf
;
510 nt_forms_struct form
;
515 for (kbuf
= tdb_firstkey(tdb_forms
);
517 newkey
= tdb_nextkey(tdb_forms
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
)
519 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) != 0)
522 dbuf
= tdb_fetch(tdb_forms
, kbuf
);
526 fstrcpy(form
.name
, kbuf
.dptr
+strlen(FORMS_PREFIX
));
527 ret
= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dddddddd",
528 &i
, &form
.flag
, &form
.width
, &form
.length
, &form
.left
,
529 &form
.top
, &form
.right
, &form
.bottom
);
530 SAFE_FREE(dbuf
.dptr
);
531 if (ret
!= dbuf
.dsize
)
534 tl
= Realloc(*list
, sizeof(nt_forms_struct
)*(n
+1));
536 DEBUG(0,("get_ntforms: Realloc fail.\n"));
548 /****************************************************************************
549 write a form struct list
550 ****************************************************************************/
551 int write_ntforms(nt_forms_struct
**list
, int number
)
558 for (i
=0;i
<number
;i
++) {
559 /* save index, so list is rebuilt in correct order */
560 len
= tdb_pack(buf
, sizeof(buf
), "dddddddd",
561 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
562 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
564 if (len
> sizeof(buf
)) break;
565 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[i
].name
);
566 kbuf
.dsize
= strlen(key
)+1;
570 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) break;
576 /****************************************************************************
577 add a form struct at the end of the list
578 ****************************************************************************/
579 BOOL
add_a_form(nt_forms_struct
**list
, const FORM
*form
, int *count
)
587 * NT tries to add forms even when
588 * they are already in the base
589 * only update the values if already present
594 unistr2_to_ascii(form_name
, &form
->name
, sizeof(form_name
)-1);
595 for (n
=0; n
<*count
; n
++) {
596 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
597 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name
));
604 if((tl
=Realloc(*list
, (n
+1)*sizeof(nt_forms_struct
))) == NULL
) {
605 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
609 unistr2_to_ascii((*list
)[n
].name
, &form
->name
, sizeof((*list
)[n
].name
)-1);
613 (*list
)[n
].flag
=form
->flags
;
614 (*list
)[n
].width
=form
->size_x
;
615 (*list
)[n
].length
=form
->size_y
;
616 (*list
)[n
].left
=form
->left
;
617 (*list
)[n
].top
=form
->top
;
618 (*list
)[n
].right
=form
->right
;
619 (*list
)[n
].bottom
=form
->bottom
;
624 /****************************************************************************
625 Delete a named form struct.
626 ****************************************************************************/
628 BOOL
delete_a_form(nt_forms_struct
**list
, UNISTR2
*del_name
, int *count
, WERROR
*ret
)
637 unistr2_to_ascii(form_name
, del_name
, sizeof(form_name
)-1);
639 for (n
=0; n
<*count
; n
++) {
640 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
641 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name
));
647 DEBUG(10,("delete_a_form, [%s] not found\n", form_name
));
648 *ret
= WERR_INVALID_PARAM
;
652 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[n
].name
);
653 kbuf
.dsize
= strlen(key
)+1;
655 if (tdb_delete(tdb_forms
, kbuf
) != 0) {
663 /****************************************************************************
664 Update a form struct.
665 ****************************************************************************/
667 void update_a_form(nt_forms_struct
**list
, const FORM
*form
, int count
)
671 unistr2_to_ascii(form_name
, &(form
->name
), sizeof(form_name
)-1);
673 DEBUG(106, ("[%s]\n", form_name
));
674 for (n
=0; n
<count
; n
++) {
675 DEBUGADD(106, ("n [%d]:[%s]\n", n
, (*list
)[n
].name
));
676 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
)))
680 if (n
==count
) return;
682 (*list
)[n
].flag
=form
->flags
;
683 (*list
)[n
].width
=form
->size_x
;
684 (*list
)[n
].length
=form
->size_y
;
685 (*list
)[n
].left
=form
->left
;
686 (*list
)[n
].top
=form
->top
;
687 (*list
)[n
].right
=form
->right
;
688 (*list
)[n
].bottom
=form
->bottom
;
691 /****************************************************************************
692 Get the nt drivers list.
693 Traverse the database and look-up the matching names.
694 ****************************************************************************/
695 int get_ntdrivers(fstring
**list
, const char *architecture
, uint32 version
)
698 const char *short_archi
;
701 TDB_DATA kbuf
, newkey
;
703 short_archi
= get_short_archi(architecture
);
704 slprintf(key
, sizeof(key
)-1, "%s%s/%d/", DRIVERS_PREFIX
, short_archi
, version
);
706 for (kbuf
= tdb_firstkey(tdb_drivers
);
708 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
710 if (strncmp(kbuf
.dptr
, key
, strlen(key
)) != 0)
713 if((fl
= Realloc(*list
, sizeof(fstring
)*(total
+1))) == NULL
) {
714 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
719 fstrcpy((*list
)[total
], kbuf
.dptr
+strlen(key
));
726 /****************************************************************************
727 function to do the mapping between the long architecture name and
729 ****************************************************************************/
730 const char *get_short_archi(const char *long_archi
)
734 DEBUG(107,("Getting architecture dependant directory\n"));
737 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
738 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
740 if (archi_table
[i
].long_archi
==NULL
) {
741 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
745 /* this might be client code - but shouldn't this be an fstrcpy etc? */
748 DEBUGADD(108,("index: [%d]\n", i
));
749 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
750 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
752 return archi_table
[i
].short_archi
;
755 /****************************************************************************
756 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
757 There are two case to be covered here: PE (Portable Executable) and NE (New
758 Executable) files. Both files support the same INFO structure, but PE files
759 store the signature in unicode, and NE files store it as !unicode.
760 returns -1 on error, 1 on version info found, and 0 on no version info found.
761 ****************************************************************************/
763 static int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
769 if ((buf
=malloc(PE_HEADER_SIZE
)) == NULL
) {
770 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
771 fname
, PE_HEADER_SIZE
));
775 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
776 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
777 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
778 fname
, (unsigned long)byte_count
));
779 goto no_version_info
;
782 /* Is this really a DOS header? */
783 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
784 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
785 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
786 goto no_version_info
;
789 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
790 if (SMB_VFS_LSEEK(fsp
, fsp
->fd
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
791 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
793 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
794 goto no_version_info
;
797 if ((byte_count
= vfs_read_data(fsp
, buf
, PE_HEADER_SIZE
)) < PE_HEADER_SIZE
) {
798 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
799 fname
, (unsigned long)byte_count
));
800 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
801 goto no_version_info
;
804 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
805 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
806 unsigned int num_sections
;
807 unsigned int section_table_bytes
;
809 if (SVAL(buf
,PE_HEADER_MACHINE_OFFSET
) != PE_HEADER_MACHINE_I386
) {
810 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
811 fname
, SVAL(buf
,PE_HEADER_MACHINE_OFFSET
)));
812 /* At this point, we assume the file is in error. It still could be somthing
813 * else besides a PE file, but it unlikely at this point.
818 /* get the section table */
819 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
820 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
821 if (section_table_bytes
== 0)
825 if ((buf
=malloc(section_table_bytes
)) == NULL
) {
826 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
827 fname
, section_table_bytes
));
831 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
832 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
833 fname
, (unsigned long)byte_count
));
837 /* Iterate the section table looking for the resource section ".rsrc" */
838 for (i
= 0; i
< num_sections
; i
++) {
839 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
841 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
842 unsigned int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
843 unsigned int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
845 if (section_bytes
== 0)
849 if ((buf
=malloc(section_bytes
)) == NULL
) {
850 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
851 fname
, section_bytes
));
855 /* Seek to the start of the .rsrc section info */
856 if (SMB_VFS_LSEEK(fsp
, fsp
->fd
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
857 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
862 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
863 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
864 fname
, (unsigned long)byte_count
));
868 if (section_bytes
< VS_VERSION_INFO_UNICODE_SIZE
)
871 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
872 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
873 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
874 /* Align to next long address */
875 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
877 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
878 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
879 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
881 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
882 fname
, *major
, *minor
,
883 (*major
>>16)&0xffff, *major
&0xffff,
884 (*minor
>>16)&0xffff, *minor
&0xffff));
893 /* Version info not found, fall back to origin date/time */
894 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
898 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
899 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
900 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
901 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
902 /* At this point, we assume the file is in error. It still could be somthing
903 * else besides a NE file, but it unlikely at this point. */
907 /* Allocate a bit more space to speed up things */
909 if ((buf
=malloc(VS_NE_BUF_SIZE
)) == NULL
) {
910 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
911 fname
, PE_HEADER_SIZE
));
915 /* This is a HACK! I got tired of trying to sort through the messy
916 * 'NE' file format. If anyone wants to clean this up please have at
917 * it, but this works. 'NE' files will eventually fade away. JRR */
918 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
919 /* Cover case that should not occur in a well formed 'NE' .dll file */
920 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
922 for(i
=0; i
<byte_count
; i
++) {
923 /* Fast skip past data that can't possibly match */
924 if (buf
[i
] != 'V') continue;
926 /* Potential match data crosses buf boundry, move it to beginning
927 * of buf, and fill the buf with as much as it will hold. */
928 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
931 memcpy(buf
, &buf
[i
], byte_count
-i
);
932 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
933 (byte_count
-i
))) < 0) {
935 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
940 byte_count
= bc
+ (byte_count
- i
);
941 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
946 /* Check that the full signature string and the magic number that
947 * follows exist (not a perfect solution, but the chances that this
948 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
949 * twice, as it is simpler to read the code. */
950 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
951 /* Compute skip alignment to next long address */
952 int skip
= -(SMB_VFS_LSEEK(fsp
, fsp
->fd
, 0, SEEK_CUR
) - (byte_count
- i
) +
953 sizeof(VS_SIGNATURE
)) & 3;
954 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
956 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
957 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
958 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
959 fname
, *major
, *minor
,
960 (*major
>>16)&0xffff, *major
&0xffff,
961 (*minor
>>16)&0xffff, *minor
&0xffff));
968 /* Version info not found, fall back to origin date/time */
969 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
974 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
975 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
976 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
987 /****************************************************************************
988 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
989 share one or more files. During the MS installation process files are checked
990 to insure that only a newer version of a shared file is installed over an
991 older version. There are several possibilities for this comparison. If there
992 is no previous version, the new one is newer (obviously). If either file is
993 missing the version info structure, compare the creation date (on Unix use
994 the modification date). Otherwise chose the numerically larger version number.
995 ****************************************************************************/
997 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
999 BOOL use_version
= True
;
1004 time_t new_create_time
;
1008 time_t old_create_time
;
1012 files_struct
*fsp
= NULL
;
1014 SMB_STRUCT_STAT stat_buf
;
1018 ZERO_STRUCT(stat_buf
);
1019 new_create_time
= (time_t)0;
1020 old_create_time
= (time_t)0;
1022 /* Get file version info (if available) for previous file (if it exists) */
1023 pstrcpy(filepath
, old_file
);
1025 driver_unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1027 fsp
= open_file_shared(conn
, filepath
, &stat_buf
,
1028 SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
1029 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1030 FILE_ATTRIBUTE_NORMAL
, INTERNAL_OPEN_ONLY
, &access_mode
, &action
);
1032 /* Old file not found, so by definition new file is in fact newer */
1033 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1038 int ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
1039 if (ret
== -1) goto error_exit
;
1042 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1044 use_version
= False
;
1045 if (SMB_VFS_FSTAT(fsp
, fsp
->fd
, &st
) == -1) goto error_exit
;
1046 old_create_time
= st
.st_mtime
;
1047 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time
));
1050 close_file(fsp
, True
);
1052 /* Get file version info (if available) for new file */
1053 pstrcpy(filepath
, new_file
);
1054 driver_unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1056 fsp
= open_file_shared(conn
, filepath
, &stat_buf
,
1057 SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
1058 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1059 FILE_ATTRIBUTE_NORMAL
, INTERNAL_OPEN_ONLY
, &access_mode
, &action
);
1061 /* New file not found, this shouldn't occur if the caller did its job */
1062 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1067 int ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
1068 if (ret
== -1) goto error_exit
;
1071 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1073 use_version
= False
;
1074 if (SMB_VFS_FSTAT(fsp
, fsp
->fd
, &st
) == -1) goto error_exit
;
1075 new_create_time
= st
.st_mtime
;
1076 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time
));
1079 close_file(fsp
, True
);
1081 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
1082 /* Compare versions and choose the larger version number */
1083 if (new_major
> old_major
||
1084 (new_major
== old_major
&& new_minor
> old_minor
)) {
1086 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1090 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1095 /* Compare modification time/dates and choose the newest time/date */
1096 if (new_create_time
> old_create_time
) {
1097 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1101 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1108 close_file(fsp
, True
);
1112 /****************************************************************************
1113 Determine the correct cVersion associated with an architecture and driver
1114 ****************************************************************************/
1115 static uint32
get_correct_cversion(const char *architecture
, fstring driverpath_in
,
1116 struct current_user
*user
, WERROR
*perr
)
1125 files_struct
*fsp
= NULL
;
1128 connection_struct
*conn
;
1132 *perr
= WERR_INVALID_PARAM
;
1134 /* If architecture is Windows 95/98/ME, the version is always 0. */
1135 if (strcmp(architecture
, "WIN40") == 0) {
1136 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1142 * Connect to the print$ share under the same account as the user connected
1143 * to the rpc pipe. Note we must still be root to do this.
1146 /* Null password is ok - we are already an authenticated user... */
1147 null_pw
= data_blob(NULL
, 0);
1148 fstrcpy(res_type
, "A:");
1150 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1154 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1155 *perr
= ntstatus_to_werror(nt_status
);
1159 /* We are temporarily becoming the connection user. */
1160 if (!become_user(conn
, user
->vuid
)) {
1161 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1162 *perr
= WERR_ACCESS_DENIED
;
1166 /* Open the driver file (Portable Executable format) and determine the
1167 * deriver the cversion. */
1168 slprintf(driverpath
, sizeof(driverpath
)-1, "%s/%s", architecture
, driverpath_in
);
1170 driver_unix_convert(driverpath
,conn
,NULL
,&bad_path
,&st
);
1172 fsp
= open_file_shared(conn
, driverpath
, &st
,
1173 SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
1174 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1175 FILE_ATTRIBUTE_NORMAL
, INTERNAL_OPEN_ONLY
, &access_mode
, &action
);
1177 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1178 driverpath
, errno
));
1179 *perr
= WERR_ACCESS_DENIED
;
1185 int ret
= get_file_version(fsp
, driverpath
, &major
, &minor
);
1186 if (ret
== -1) goto error_exit
;
1189 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath
));
1194 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1195 * for more details. Version in this case is not just the version of the
1196 * file, but the version in the sense of kernal mode (2) vs. user mode
1197 * (3) drivers. Other bits of the version fields are the version info.
1200 cversion
= major
& 0x0000ffff;
1202 case 2: /* WinNT drivers */
1203 case 3: /* Win2K drivers */
1207 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1208 driverpath
, cversion
));
1212 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1213 driverpath
, major
, minor
));
1216 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1217 driverpath
, cversion
));
1219 close_file(fsp
, True
);
1220 close_cnum(conn
, user
->vuid
);
1229 close_file(fsp
, True
);
1231 close_cnum(conn
, user
->vuid
);
1236 /****************************************************************************
1237 ****************************************************************************/
1238 static WERROR
clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
,
1239 struct current_user
*user
)
1241 const char *architecture
;
1247 /* clean up the driver name.
1248 * we can get .\driver.dll
1249 * or worse c:\windows\system\driver.dll !
1251 /* using an intermediate string to not have overlaping memcpy()'s */
1252 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1253 fstrcpy(new_name
, p
+1);
1254 fstrcpy(driver
->driverpath
, new_name
);
1257 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1258 fstrcpy(new_name
, p
+1);
1259 fstrcpy(driver
->datafile
, new_name
);
1262 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1263 fstrcpy(new_name
, p
+1);
1264 fstrcpy(driver
->configfile
, new_name
);
1267 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1268 fstrcpy(new_name
, p
+1);
1269 fstrcpy(driver
->helpfile
, new_name
);
1272 if (driver
->dependentfiles
) {
1273 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1274 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1275 fstrcpy(new_name
, p
+1);
1276 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1281 architecture
= get_short_archi(driver
->environment
);
1283 /* jfm:7/16/2000 the client always sends the cversion=0.
1284 * The server should check which version the driver is by reading
1285 * the PE header of driver->driverpath.
1287 * For Windows 95/98 the version is 0 (so the value sent is correct)
1288 * For Windows NT (the architecture doesn't matter)
1289 * NT 3.1: cversion=0
1290 * NT 3.5/3.51: cversion=1
1294 if ((driver
->cversion
= get_correct_cversion( architecture
,
1295 driver
->driverpath
, user
, &err
)) == -1)
1301 /****************************************************************************
1302 ****************************************************************************/
1303 static WERROR
clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
, struct current_user
*user
)
1305 const char *architecture
;
1311 /* clean up the driver name.
1312 * we can get .\driver.dll
1313 * or worse c:\windows\system\driver.dll !
1315 /* using an intermediate string to not have overlaping memcpy()'s */
1316 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1317 fstrcpy(new_name
, p
+1);
1318 fstrcpy(driver
->driverpath
, new_name
);
1321 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1322 fstrcpy(new_name
, p
+1);
1323 fstrcpy(driver
->datafile
, new_name
);
1326 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1327 fstrcpy(new_name
, p
+1);
1328 fstrcpy(driver
->configfile
, new_name
);
1331 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1332 fstrcpy(new_name
, p
+1);
1333 fstrcpy(driver
->helpfile
, new_name
);
1336 if (driver
->dependentfiles
) {
1337 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1338 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1339 fstrcpy(new_name
, p
+1);
1340 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1345 architecture
= get_short_archi(driver
->environment
);
1347 /* jfm:7/16/2000 the client always sends the cversion=0.
1348 * The server should check which version the driver is by reading
1349 * the PE header of driver->driverpath.
1351 * For Windows 95/98 the version is 0 (so the value sent is correct)
1352 * For Windows NT (the architecture doesn't matter)
1353 * NT 3.1: cversion=0
1354 * NT 3.5/3.51: cversion=1
1358 if ((driver
->version
= get_correct_cversion(architecture
, driver
->driverpath
, user
, &err
)) == -1)
1364 /****************************************************************************
1365 ****************************************************************************/
1366 WERROR
clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
,
1367 uint32 level
, struct current_user
*user
)
1372 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1373 driver
=driver_abstract
.info_3
;
1374 return clean_up_driver_struct_level_3(driver
, user
);
1378 NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
;
1379 driver
=driver_abstract
.info_6
;
1380 return clean_up_driver_struct_level_6(driver
, user
);
1383 return WERR_INVALID_PARAM
;
1387 /****************************************************************************
1388 This function sucks and should be replaced. JRA.
1389 ****************************************************************************/
1391 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*dst
, NT_PRINTER_DRIVER_INFO_LEVEL_6
*src
)
1393 dst
->cversion
= src
->version
;
1395 fstrcpy( dst
->name
, src
->name
);
1396 fstrcpy( dst
->environment
, src
->environment
);
1397 fstrcpy( dst
->driverpath
, src
->driverpath
);
1398 fstrcpy( dst
->datafile
, src
->datafile
);
1399 fstrcpy( dst
->configfile
, src
->configfile
);
1400 fstrcpy( dst
->helpfile
, src
->helpfile
);
1401 fstrcpy( dst
->monitorname
, src
->monitorname
);
1402 fstrcpy( dst
->defaultdatatype
, src
->defaultdatatype
);
1403 dst
->dependentfiles
= src
->dependentfiles
;
1406 #if 0 /* Debugging function */
1408 static char* ffmt(unsigned char *c
){
1410 static char ffmt_str
[17];
1412 for (i
=0; i
<16; i
++) {
1413 if ((c
[i
] < ' ') || (c
[i
] > '~'))
1424 /****************************************************************************
1425 ****************************************************************************/
1426 BOOL
move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
, uint32 level
,
1427 struct current_user
*user
, WERROR
*perr
)
1429 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1430 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver
;
1431 const char *architecture
;
1436 connection_struct
*conn
;
1446 memset(inbuf
, '\0', sizeof(inbuf
));
1447 memset(outbuf
, '\0', sizeof(outbuf
));
1451 driver
=driver_abstract
.info_3
;
1452 else if (level
==6) {
1453 convert_level_6_to_level3(&converted_driver
, driver_abstract
.info_6
);
1454 driver
= &converted_driver
;
1456 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level
));
1460 architecture
= get_short_archi(driver
->environment
);
1463 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1464 * Note we must be root to do this.
1467 null_pw
= data_blob(NULL
, 0);
1468 fstrcpy(res_type
, "A:");
1470 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1474 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1475 *perr
= ntstatus_to_werror(nt_status
);
1480 * Save who we are - we are temporarily becoming the connection user.
1483 if (!become_user(conn
, conn
->vuid
)) {
1484 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1489 * make the directories version and version\driver_name
1490 * under the architecture directory.
1492 DEBUG(5,("Creating first directory\n"));
1493 slprintf(new_dir
, sizeof(new_dir
)-1, "%s/%d", architecture
, driver
->cversion
);
1494 driver_unix_convert(new_dir
, conn
, NULL
, &bad_path
, &st
);
1495 mkdir_internal(conn
, new_dir
);
1497 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1498 * listed for this driver which has already been moved, skip it (note:
1499 * drivers may list the same file name several times. Then check if the
1500 * file already exists in archi\cversion\, if so, check that the version
1501 * info (or time stamps if version info is unavailable) is newer (or the
1502 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1503 * Otherwise, delete the file.
1505 * If a file is not moved to archi\cversion\ because of an error, all the
1506 * rest of the 'unmoved' driver files are removed from archi\. If one or
1507 * more of the driver's files was already moved to archi\cversion\, it
1508 * potentially leaves the driver in a partially updated state. Version
1509 * trauma will most likely occur if an client attempts to use any printer
1510 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1511 * done is appropriate... later JRR
1514 DEBUG(5,("Moving files now !\n"));
1516 if (driver
->driverpath
&& strlen(driver
->driverpath
)) {
1517 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->driverpath
);
1518 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->driverpath
);
1519 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1521 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1522 status
= rename_internals(conn
, new_name
, old_name
, 0, True
);
1523 if (!NT_STATUS_IS_OK(status
)) {
1524 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1525 new_name
, old_name
));
1526 *perr
= ntstatus_to_werror(status
);
1527 unlink_internals(conn
, 0, new_name
);
1531 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1532 unlink_internals(conn
, 0, new_name
);
1536 if (driver
->datafile
&& strlen(driver
->datafile
)) {
1537 if (!strequal(driver
->datafile
, driver
->driverpath
)) {
1538 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->datafile
);
1539 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->datafile
);
1540 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1542 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1543 status
= rename_internals(conn
, new_name
, old_name
, 0, True
);
1544 if (!NT_STATUS_IS_OK(status
)) {
1545 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1546 new_name
, old_name
));
1547 *perr
= ntstatus_to_werror(status
);
1548 unlink_internals(conn
, 0, new_name
);
1552 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1553 unlink_internals(conn
, 0, new_name
);
1558 if (driver
->configfile
&& strlen(driver
->configfile
)) {
1559 if (!strequal(driver
->configfile
, driver
->driverpath
) &&
1560 !strequal(driver
->configfile
, driver
->datafile
)) {
1561 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->configfile
);
1562 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->configfile
);
1563 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1565 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1566 status
= rename_internals(conn
, new_name
, old_name
, 0, True
);
1567 if (!NT_STATUS_IS_OK(status
)) {
1568 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1569 new_name
, old_name
));
1570 *perr
= ntstatus_to_werror(status
);
1571 unlink_internals(conn
, 0, new_name
);
1575 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1576 unlink_internals(conn
, 0, new_name
);
1581 if (driver
->helpfile
&& strlen(driver
->helpfile
)) {
1582 if (!strequal(driver
->helpfile
, driver
->driverpath
) &&
1583 !strequal(driver
->helpfile
, driver
->datafile
) &&
1584 !strequal(driver
->helpfile
, driver
->configfile
)) {
1585 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->helpfile
);
1586 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->helpfile
);
1587 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1589 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1590 status
= rename_internals(conn
, new_name
, old_name
, 0, True
);
1591 if (!NT_STATUS_IS_OK(status
)) {
1592 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1593 new_name
, old_name
));
1594 *perr
= ntstatus_to_werror(status
);
1595 unlink_internals(conn
, 0, new_name
);
1599 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1600 unlink_internals(conn
, 0, new_name
);
1605 if (driver
->dependentfiles
) {
1606 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1607 if (!strequal(driver
->dependentfiles
[i
], driver
->driverpath
) &&
1608 !strequal(driver
->dependentfiles
[i
], driver
->datafile
) &&
1609 !strequal(driver
->dependentfiles
[i
], driver
->configfile
) &&
1610 !strequal(driver
->dependentfiles
[i
], driver
->helpfile
)) {
1612 for (j
=0; j
< i
; j
++) {
1613 if (strequal(driver
->dependentfiles
[i
], driver
->dependentfiles
[j
])) {
1618 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->dependentfiles
[i
]);
1619 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->dependentfiles
[i
]);
1620 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1622 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1623 status
= rename_internals(conn
, new_name
, old_name
, 0, True
);
1624 if (!NT_STATUS_IS_OK(status
)) {
1625 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1626 new_name
, old_name
));
1627 *perr
= ntstatus_to_werror(status
);
1628 unlink_internals(conn
, 0, new_name
);
1632 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1633 unlink_internals(conn
, 0, new_name
);
1640 close_cnum(conn
, user
->vuid
);
1643 return ver
== -1 ? False
: True
;
1646 /****************************************************************************
1647 ****************************************************************************/
1648 static uint32
add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
)
1651 const char *architecture
;
1657 TDB_DATA kbuf
, dbuf
;
1659 architecture
= get_short_archi(driver
->environment
);
1661 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1662 * \\server is added in the rpc server layer.
1663 * It does make sense to NOT store the server's name in the printer TDB.
1666 slprintf(directory
, sizeof(directory
)-1, "\\print$\\%s\\%d\\", architecture
, driver
->cversion
);
1668 /* .inf files do not always list a file for each of the four standard files.
1669 * Don't prepend a path to a null filename, or client claims:
1670 * "The server on which the printer resides does not have a suitable
1671 * <printer driver name> printer driver installed. Click OK if you
1672 * wish to install the driver on your local machine."
1674 if (strlen(driver
->driverpath
)) {
1675 fstrcpy(temp_name
, driver
->driverpath
);
1676 slprintf(driver
->driverpath
, sizeof(driver
->driverpath
)-1, "%s%s", directory
, temp_name
);
1679 if (strlen(driver
->datafile
)) {
1680 fstrcpy(temp_name
, driver
->datafile
);
1681 slprintf(driver
->datafile
, sizeof(driver
->datafile
)-1, "%s%s", directory
, temp_name
);
1684 if (strlen(driver
->configfile
)) {
1685 fstrcpy(temp_name
, driver
->configfile
);
1686 slprintf(driver
->configfile
, sizeof(driver
->configfile
)-1, "%s%s", directory
, temp_name
);
1689 if (strlen(driver
->helpfile
)) {
1690 fstrcpy(temp_name
, driver
->helpfile
);
1691 slprintf(driver
->helpfile
, sizeof(driver
->helpfile
)-1, "%s%s", directory
, temp_name
);
1694 if (driver
->dependentfiles
) {
1695 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1696 fstrcpy(temp_name
, driver
->dependentfiles
[i
]);
1697 slprintf(driver
->dependentfiles
[i
], sizeof(driver
->dependentfiles
[i
])-1, "%s%s", directory
, temp_name
);
1701 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, driver
->cversion
, driver
->name
);
1703 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key
));
1710 len
+= tdb_pack(buf
+len
, buflen
-len
, "dffffffff",
1713 driver
->environment
,
1718 driver
->monitorname
,
1719 driver
->defaultdatatype
);
1721 if (driver
->dependentfiles
) {
1722 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1723 len
+= tdb_pack(buf
+len
, buflen
-len
, "f",
1724 driver
->dependentfiles
[i
]);
1728 if (len
!= buflen
) {
1731 tb
= (char *)Realloc(buf
, len
);
1733 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1744 kbuf
.dsize
= strlen(key
)+1;
1748 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
1752 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key
));
1758 /****************************************************************************
1759 ****************************************************************************/
1760 static uint32
add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
)
1762 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3
;
1765 info3
.cversion
= driver
->version
;
1766 fstrcpy(info3
.name
,driver
->name
);
1767 fstrcpy(info3
.environment
,driver
->environment
);
1768 fstrcpy(info3
.driverpath
,driver
->driverpath
);
1769 fstrcpy(info3
.datafile
,driver
->datafile
);
1770 fstrcpy(info3
.configfile
,driver
->configfile
);
1771 fstrcpy(info3
.helpfile
,driver
->helpfile
);
1772 fstrcpy(info3
.monitorname
,driver
->monitorname
);
1773 fstrcpy(info3
.defaultdatatype
,driver
->defaultdatatype
);
1774 info3
.dependentfiles
= driver
->dependentfiles
;
1776 return add_a_printer_driver_3(&info3
);
1780 /****************************************************************************
1781 ****************************************************************************/
1782 static WERROR
get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, const char *driver
, const char *arch
)
1784 NT_PRINTER_DRIVER_INFO_LEVEL_3 info
;
1788 fstrcpy(info
.name
, driver
);
1789 fstrcpy(info
.defaultdatatype
, "RAW");
1791 fstrcpy(info
.driverpath
, "");
1792 fstrcpy(info
.datafile
, "");
1793 fstrcpy(info
.configfile
, "");
1794 fstrcpy(info
.helpfile
, "");
1796 if ((info
.dependentfiles
=(fstring
*)malloc(2*sizeof(fstring
))) == NULL
)
1799 memset(info
.dependentfiles
, '\0', 2*sizeof(fstring
));
1800 fstrcpy(info
.dependentfiles
[0], "");
1802 *info_ptr
= memdup(&info
, sizeof(info
));
1807 /****************************************************************************
1808 ****************************************************************************/
1809 static WERROR
get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, fstring drivername
, const char *arch
, uint32 version
)
1811 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver
;
1812 TDB_DATA kbuf
, dbuf
;
1813 const char *architecture
;
1818 ZERO_STRUCT(driver
);
1820 architecture
= get_short_archi(arch
);
1822 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1824 if ( strcmp( architecture
, SPL_ARCH_WIN40
) == 0 )
1827 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX
, architecture
, version
, drivername
));
1829 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, version
, drivername
);
1832 kbuf
.dsize
= strlen(key
)+1;
1834 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
1836 return WERR_UNKNOWN_PRINTER_DRIVER
;
1838 len
+= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dffffffff",
1847 driver
.defaultdatatype
);
1850 while (len
< dbuf
.dsize
) {
1853 tddfs
= (fstring
*)Realloc(driver
.dependentfiles
,
1854 sizeof(fstring
)*(i
+2));
1855 if (tddfs
== NULL
) {
1856 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1859 else driver
.dependentfiles
= tddfs
;
1861 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "f",
1862 &driver
.dependentfiles
[i
]);
1866 if (driver
.dependentfiles
!= NULL
)
1867 fstrcpy(driver
.dependentfiles
[i
], "");
1869 SAFE_FREE(dbuf
.dptr
);
1871 if (len
!= dbuf
.dsize
) {
1872 SAFE_FREE(driver
.dependentfiles
);
1874 return get_a_printer_driver_3_default(info_ptr
, drivername
, arch
);
1877 *info_ptr
= (NT_PRINTER_DRIVER_INFO_LEVEL_3
*)memdup(&driver
, sizeof(driver
));
1882 /****************************************************************************
1883 Debugging function, dump at level 6 the struct in the logs.
1884 ****************************************************************************/
1886 static uint32
dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
1889 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
1892 DEBUG(20,("Dumping printer driver at level [%d]\n", level
));
1898 if (driver
.info_3
== NULL
)
1901 info3
=driver
.info_3
;
1903 DEBUGADD(20,("version:[%d]\n", info3
->cversion
));
1904 DEBUGADD(20,("name:[%s]\n", info3
->name
));
1905 DEBUGADD(20,("environment:[%s]\n", info3
->environment
));
1906 DEBUGADD(20,("driverpath:[%s]\n", info3
->driverpath
));
1907 DEBUGADD(20,("datafile:[%s]\n", info3
->datafile
));
1908 DEBUGADD(20,("configfile:[%s]\n", info3
->configfile
));
1909 DEBUGADD(20,("helpfile:[%s]\n", info3
->helpfile
));
1910 DEBUGADD(20,("monitorname:[%s]\n", info3
->monitorname
));
1911 DEBUGADD(20,("defaultdatatype:[%s]\n", info3
->defaultdatatype
));
1913 for (i
=0; info3
->dependentfiles
&&
1914 *info3
->dependentfiles
[i
]; i
++) {
1915 DEBUGADD(20,("dependentfile:[%s]\n",
1916 info3
->dependentfiles
[i
]));
1923 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level
));
1931 /****************************************************************************
1932 ****************************************************************************/
1933 int pack_devicemode(NT_DEVICEMODE
*nt_devmode
, char *buf
, int buflen
)
1937 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", nt_devmode
);
1942 len
+= tdb_pack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1943 nt_devmode
->devicename
,
1944 nt_devmode
->formname
,
1946 nt_devmode
->specversion
,
1947 nt_devmode
->driverversion
,
1949 nt_devmode
->driverextra
,
1950 nt_devmode
->orientation
,
1951 nt_devmode
->papersize
,
1952 nt_devmode
->paperlength
,
1953 nt_devmode
->paperwidth
,
1956 nt_devmode
->defaultsource
,
1957 nt_devmode
->printquality
,
1960 nt_devmode
->yresolution
,
1961 nt_devmode
->ttoption
,
1962 nt_devmode
->collate
,
1963 nt_devmode
->logpixels
,
1966 nt_devmode
->bitsperpel
,
1967 nt_devmode
->pelswidth
,
1968 nt_devmode
->pelsheight
,
1969 nt_devmode
->displayflags
,
1970 nt_devmode
->displayfrequency
,
1971 nt_devmode
->icmmethod
,
1972 nt_devmode
->icmintent
,
1973 nt_devmode
->mediatype
,
1974 nt_devmode
->dithertype
,
1975 nt_devmode
->reserved1
,
1976 nt_devmode
->reserved2
,
1977 nt_devmode
->panningwidth
,
1978 nt_devmode
->panningheight
,
1979 nt_devmode
->private);
1982 if (nt_devmode
->private) {
1983 len
+= tdb_pack(buf
+len
, buflen
-len
, "B",
1984 nt_devmode
->driverextra
,
1985 nt_devmode
->private);
1988 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode
->formname
));
1993 /****************************************************************************
1994 Pack all values in all printer keys
1995 ***************************************************************************/
1997 static int pack_values(NT_PRINTER_DATA
*data
, char *buf
, int buflen
)
2001 REGISTRY_VALUE
*val
;
2002 REGVAL_CTR
*val_ctr
;
2009 /* loop over all keys */
2011 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2012 val_ctr
= &data
->keys
[i
].values
;
2013 num_values
= regval_ctr_numvals( val_ctr
);
2015 /* loop over all values */
2017 for ( j
=0; j
<num_values
; j
++ ) {
2018 /* pathname should be stored as <key>\<value> */
2020 val
= regval_ctr_specific_value( val_ctr
, j
);
2021 pstrcpy( path
, data
->keys
[i
].name
);
2022 pstrcat( path
, "\\" );
2023 pstrcat( path
, regval_name(val
) );
2025 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2030 regval_data_p(val
) );
2037 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", NULL
);
2043 /****************************************************************************
2044 Delete a printer - this just deletes the printer info file, any open
2045 handles are not affected.
2046 ****************************************************************************/
2048 uint32
del_a_printer(char *sharename
)
2053 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
2056 kbuf
.dsize
=strlen(key
)+1;
2058 tdb_delete(tdb_printers
, kbuf
);
2062 /****************************************************************************
2063 ****************************************************************************/
2064 static WERROR
update_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
)
2070 TDB_DATA kbuf
, dbuf
;
2073 * in addprinter: no servername and the printer is the name
2074 * in setprinter: servername is \\server
2075 * and printer is \\server\\printer
2077 * Samba manages only local printers.
2078 * we currently don't support things like i
2079 * path=\\other_server\printer
2081 * We only store the printername, not \\server\printername
2084 if ( info
->servername
[0] != '\0' ) {
2085 trim_string(info
->printername
, info
->servername
, NULL
);
2086 trim_char(info
->printername
, '\\', '\0');
2087 info
->servername
[0]='\0';
2091 * JFM: one day I'll forget.
2092 * below that's info->portname because that's the SAMBA sharename
2093 * and I made NT 'thinks' it's the portname
2094 * the info->sharename is the thing you can name when you add a printer
2095 * that's the short-name when you create shared printer for 95/98
2096 * So I've made a limitation in SAMBA: you can only have 1 printer model
2097 * behind a SAMBA share.
2105 len
+= tdb_pack(buf
+len
, buflen
-len
, "dddddddddddfffffPfffff",
2108 info
->default_priority
,
2125 info
->printprocessor
,
2129 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
2131 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
2133 if (buflen
!= len
) {
2136 tb
= (char *)Realloc(buf
, len
);
2138 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2148 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, info
->sharename
);
2151 kbuf
.dsize
= strlen(key
)+1;
2155 ret
= (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) == 0? WERR_OK
: WERR_NOMEM
);
2158 if (!W_ERROR_IS_OK(ret
))
2159 DEBUG(8, ("error updating printer to tdb on disk\n"));
2163 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2164 info
->sharename
, info
->drivername
, info
->portname
, len
));
2170 /****************************************************************************
2171 Malloc and return an NT devicemode.
2172 ****************************************************************************/
2174 NT_DEVICEMODE
*construct_nt_devicemode(const fstring default_devicename
)
2177 char adevice
[MAXDEVICENAME
];
2178 NT_DEVICEMODE
*nt_devmode
= (NT_DEVICEMODE
*)malloc(sizeof(NT_DEVICEMODE
));
2180 if (nt_devmode
== NULL
) {
2181 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2185 ZERO_STRUCTP(nt_devmode
);
2187 slprintf(adevice
, sizeof(adevice
), "%s", default_devicename
);
2188 fstrcpy(nt_devmode
->devicename
, adevice
);
2190 fstrcpy(nt_devmode
->formname
, "Letter");
2192 nt_devmode
->specversion
= 0x0401;
2193 nt_devmode
->driverversion
= 0x0400;
2194 nt_devmode
->size
= 0x00DC;
2195 nt_devmode
->driverextra
= 0x0000;
2196 nt_devmode
->fields
= FORMNAME
| TTOPTION
| PRINTQUALITY
|
2197 DEFAULTSOURCE
| COPIES
| SCALE
|
2198 PAPERSIZE
| ORIENTATION
;
2199 nt_devmode
->orientation
= 1;
2200 nt_devmode
->papersize
= PAPER_LETTER
;
2201 nt_devmode
->paperlength
= 0;
2202 nt_devmode
->paperwidth
= 0;
2203 nt_devmode
->scale
= 0x64;
2204 nt_devmode
->copies
= 1;
2205 nt_devmode
->defaultsource
= BIN_FORMSOURCE
;
2206 nt_devmode
->printquality
= RES_HIGH
; /* 0x0258 */
2207 nt_devmode
->color
= COLOR_MONOCHROME
;
2208 nt_devmode
->duplex
= DUP_SIMPLEX
;
2209 nt_devmode
->yresolution
= 0;
2210 nt_devmode
->ttoption
= TT_SUBDEV
;
2211 nt_devmode
->collate
= COLLATE_FALSE
;
2212 nt_devmode
->icmmethod
= 0;
2213 nt_devmode
->icmintent
= 0;
2214 nt_devmode
->mediatype
= 0;
2215 nt_devmode
->dithertype
= 0;
2217 /* non utilisés par un driver d'imprimante */
2218 nt_devmode
->logpixels
= 0;
2219 nt_devmode
->bitsperpel
= 0;
2220 nt_devmode
->pelswidth
= 0;
2221 nt_devmode
->pelsheight
= 0;
2222 nt_devmode
->displayflags
= 0;
2223 nt_devmode
->displayfrequency
= 0;
2224 nt_devmode
->reserved1
= 0;
2225 nt_devmode
->reserved2
= 0;
2226 nt_devmode
->panningwidth
= 0;
2227 nt_devmode
->panningheight
= 0;
2229 nt_devmode
->private = NULL
;
2233 /****************************************************************************
2234 Deepcopy an NT devicemode.
2235 ****************************************************************************/
2237 NT_DEVICEMODE
*dup_nt_devicemode(NT_DEVICEMODE
*nt_devicemode
)
2239 NT_DEVICEMODE
*new_nt_devicemode
= NULL
;
2241 if ( !nt_devicemode
)
2244 if ((new_nt_devicemode
= (NT_DEVICEMODE
*)memdup(nt_devicemode
, sizeof(NT_DEVICEMODE
))) == NULL
) {
2245 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2249 new_nt_devicemode
->private = NULL
;
2250 if (nt_devicemode
->private != NULL
) {
2251 if ((new_nt_devicemode
->private = memdup(nt_devicemode
->private, nt_devicemode
->driverextra
)) == NULL
) {
2252 SAFE_FREE(new_nt_devicemode
);
2253 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2258 return new_nt_devicemode
;
2261 /****************************************************************************
2262 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2263 ****************************************************************************/
2265 void free_nt_devicemode(NT_DEVICEMODE
**devmode_ptr
)
2267 NT_DEVICEMODE
*nt_devmode
= *devmode_ptr
;
2269 if(nt_devmode
== NULL
)
2272 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2274 SAFE_FREE(nt_devmode
->private);
2275 SAFE_FREE(*devmode_ptr
);
2278 /****************************************************************************
2279 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2280 ****************************************************************************/
2281 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
)
2283 NT_PRINTER_INFO_LEVEL_2
*info
= *info_ptr
;
2284 NT_PRINTER_DATA
*data
;
2290 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2292 free_nt_devicemode(&info
->devmode
);
2294 /* clean up all registry keys */
2297 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2298 SAFE_FREE( data
->keys
[i
].name
);
2299 regval_ctr_destroy( &data
->keys
[i
].values
);
2301 SAFE_FREE( data
->keys
);
2303 /* finally the top level structure */
2305 SAFE_FREE( *info_ptr
);
2309 /****************************************************************************
2310 ****************************************************************************/
2311 int unpack_devicemode(NT_DEVICEMODE
**nt_devmode
, char *buf
, int buflen
)
2315 NT_DEVICEMODE devmode
;
2317 ZERO_STRUCT(devmode
);
2319 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2321 if (!*nt_devmode
) return len
;
2323 len
+= tdb_unpack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2327 &devmode
.specversion
,
2328 &devmode
.driverversion
,
2330 &devmode
.driverextra
,
2331 &devmode
.orientation
,
2333 &devmode
.paperlength
,
2334 &devmode
.paperwidth
,
2337 &devmode
.defaultsource
,
2338 &devmode
.printquality
,
2341 &devmode
.yresolution
,
2347 &devmode
.bitsperpel
,
2349 &devmode
.pelsheight
,
2350 &devmode
.displayflags
,
2351 &devmode
.displayfrequency
,
2355 &devmode
.dithertype
,
2358 &devmode
.panningwidth
,
2359 &devmode
.panningheight
,
2362 if (devmode
.private) {
2363 /* the len in tdb_unpack is an int value and
2364 * devmode.driverextra is only a short
2366 len
+= tdb_unpack(buf
+len
, buflen
-len
, "B", &extra_len
, &devmode
.private);
2367 devmode
.driverextra
=(uint16
)extra_len
;
2369 /* check to catch an invalid TDB entry so we don't segfault */
2370 if (devmode
.driverextra
== 0) {
2371 devmode
.private = NULL
;
2375 *nt_devmode
= (NT_DEVICEMODE
*)memdup(&devmode
, sizeof(devmode
));
2377 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode
.devicename
, devmode
.formname
));
2378 if (devmode
.private)
2379 DEBUG(8,("with a private section of %d bytes\n", devmode
.driverextra
));
2384 /****************************************************************************
2385 Allocate and initialize a new slot.
2386 ***************************************************************************/
2388 static int add_new_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2393 if ( !data
|| !name
)
2396 /* allocate another slot in the NT_PRINTER_KEY array */
2398 d
= Realloc( data
->keys
, sizeof(NT_PRINTER_KEY
)*(data
->num_keys
+1) );
2402 key_index
= data
->num_keys
;
2404 /* initialze new key */
2407 data
->keys
[key_index
].name
= strdup( name
);
2409 ZERO_STRUCTP( &data
->keys
[key_index
].values
);
2411 regval_ctr_init( &data
->keys
[key_index
].values
);
2413 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name
));
2418 /****************************************************************************
2419 search for a registry key name in the existing printer data
2420 ***************************************************************************/
2422 int lookup_printerkey( NT_PRINTER_DATA
*data
, const char *name
)
2427 if ( !data
|| !name
)
2430 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name
));
2432 /* loop over all existing keys */
2434 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2435 if ( strequal(data
->keys
[i
].name
, name
) ) {
2436 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name
));
2446 /****************************************************************************
2447 ***************************************************************************/
2449 uint32
get_printer_subkeys( NT_PRINTER_DATA
*data
, const char* key
, fstring
**subkeys
)
2453 int num_subkeys
= 0;
2455 fstring
*ptr
, *subkeys_ptr
= NULL
;
2461 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2462 if ( StrnCaseCmp(data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2463 /* match sure it is a subkey and not the key itself */
2465 key_len
= strlen( key
);
2466 if ( strlen(data
->keys
[i
].name
) == key_len
)
2469 /* get subkey path */
2471 p
= data
->keys
[i
].name
+ key_len
;
2474 fstrcpy( subkeyname
, p
);
2475 if ( (p
= strchr( subkeyname
, '\\' )) )
2478 /* don't add a key more than once */
2480 for ( j
=0; j
<num_subkeys
; j
++ ) {
2481 if ( strequal( subkeys_ptr
[j
], subkeyname
) )
2485 if ( j
!= num_subkeys
)
2488 /* found a match, so allocate space and copy the name */
2490 if ( !(ptr
= Realloc( subkeys_ptr
, (num_subkeys
+2)*sizeof(fstring
))) ) {
2491 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2493 SAFE_FREE( subkeys
);
2498 fstrcpy( subkeys_ptr
[num_subkeys
], subkeyname
);
2504 /* tag of the end */
2507 fstrcpy(subkeys_ptr
[num_subkeys
], "" );
2509 *subkeys
= subkeys_ptr
;
2515 static void map_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2518 smb_ucs2_t conv_str
[1024];
2521 regval_ctr_delvalue(ctr
, val_name
);
2522 str_size
= push_ucs2(NULL
, conv_str
, sz
, sizeof(conv_str
),
2523 STR_TERMINATE
| STR_NOALIGN
);
2524 regval_ctr_addvalue(ctr
, val_name
, REG_SZ
,
2525 (char *) conv_str
, str_size
);
2528 static void map_dword_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2531 regval_ctr_delvalue(ctr
, val_name
);
2532 regval_ctr_addvalue(ctr
, val_name
, REG_DWORD
,
2533 (char *) &dword
, sizeof(dword
));
2536 static void map_bool_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2539 uint8 bin_bool
= (b
? 1 : 0);
2540 regval_ctr_delvalue(ctr
, val_name
);
2541 regval_ctr_addvalue(ctr
, val_name
, REG_BINARY
,
2542 (char *) &bin_bool
, sizeof(bin_bool
));
2545 static void map_single_multi_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2546 const char *multi_sz
)
2548 smb_ucs2_t
*conv_strs
= NULL
;
2551 /* a multi-sz has to have a null string terminator, i.e., the last
2552 string must be followed by two nulls */
2553 str_size
= (strlen(multi_sz
) + 2) * sizeof(smb_ucs2_t
);
2554 conv_strs
= calloc(str_size
, 1);
2556 push_ucs2(NULL
, conv_strs
, multi_sz
, str_size
,
2557 STR_TERMINATE
| STR_NOALIGN
);
2559 regval_ctr_delvalue(ctr
, val_name
);
2560 regval_ctr_addvalue(ctr
, val_name
, REG_MULTI_SZ
,
2561 (char *) conv_strs
, str_size
);
2562 safe_free(conv_strs
);
2566 /****************************************************************************
2567 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2569 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2570 * @return BOOL indicating success or failure
2571 ***************************************************************************/
2573 static BOOL
map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2
*info2
)
2575 REGVAL_CTR
*ctr
= NULL
;
2577 char *allocated_string
= NULL
;
2578 const char *ascii_str
;
2581 if ((i
= lookup_printerkey(&info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2582 i
= add_new_printer_key(&info2
->data
, SPOOL_DSSPOOLER_KEY
);
2583 ctr
= &info2
->data
.keys
[i
].values
;
2585 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTERNAME
, info2
->sharename
);
2586 map_sz_into_ctr(ctr
, SPOOL_REG_SHORTSERVERNAME
, global_myname());
2588 get_mydnsfullname(longname
);
2589 map_sz_into_ctr(ctr
, SPOOL_REG_SERVERNAME
, longname
);
2591 asprintf(&allocated_string
, "\\\\%s\\%s", longname
, info2
->sharename
);
2592 map_sz_into_ctr(ctr
, SPOOL_REG_UNCNAME
, allocated_string
);
2593 SAFE_FREE(allocated_string
);
2595 map_dword_into_ctr(ctr
, SPOOL_REG_VERSIONNUMBER
, 4);
2596 map_sz_into_ctr(ctr
, SPOOL_REG_DRIVERNAME
, info2
->drivername
);
2597 map_sz_into_ctr(ctr
, SPOOL_REG_LOCATION
, info2
->location
);
2598 map_sz_into_ctr(ctr
, SPOOL_REG_DESCRIPTION
, info2
->comment
);
2599 map_single_multi_sz_into_ctr(ctr
, SPOOL_REG_PORTNAME
, info2
->portname
);
2600 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSEPARATORFILE
, info2
->sepfile
);
2601 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTSTARTTIME
, info2
->starttime
);
2602 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTENDTIME
, info2
->untiltime
);
2603 map_dword_into_ctr(ctr
, SPOOL_REG_PRIORITY
, info2
->priority
);
2605 map_bool_into_ctr(ctr
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
2606 (info2
->attributes
&
2607 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
2609 switch (info2
->attributes
& 0x3) {
2611 ascii_str
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
2614 ascii_str
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
2617 ascii_str
= SPOOL_REGVAL_PRINTDIRECT
;
2620 ascii_str
= "unknown";
2622 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSPOOLING
, ascii_str
);
2627 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2
*info2
,
2631 REGVAL_CTR
*ctr
=NULL
;
2633 /* find the DsSpooler key */
2634 if ((i
= lookup_printerkey(&info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2635 i
= add_new_printer_key(&info2
->data
, SPOOL_DSSPOOLER_KEY
);
2636 ctr
= &info2
->data
.keys
[i
].values
;
2638 regval_ctr_delvalue(ctr
, "objectGUID");
2639 regval_ctr_addvalue(ctr
, "objectGUID", REG_BINARY
,
2640 (char *) &guid
, sizeof(struct uuid
));
2643 static WERROR
nt_printer_publish_ads(ADS_STRUCT
*ads
,
2644 NT_PRINTER_INFO_LEVEL
*printer
)
2648 char *prt_dn
= NULL
, *srv_dn
, *srv_cn_0
;
2649 char *srv_dn_utf8
, **srv_cn_utf8
;
2652 const char *attrs
[] = {"objectGUID", NULL
};
2654 WERROR win_rc
= WERR_OK
;
2656 DEBUG(5, ("publishing printer %s\n", printer
->info_2
->printername
));
2658 /* figure out where to publish */
2659 ads_find_machine_acct(ads
, &res
, global_myname());
2661 /* We use ldap_get_dn here as we need the answer
2662 * in utf8 to call ldap_explode_dn(). JRA. */
2664 srv_dn_utf8
= ldap_get_dn(ads
->ld
, res
);
2667 return WERR_SERVER_UNAVAILABLE
;
2669 ads_msgfree(ads
, res
);
2670 srv_cn_utf8
= ldap_explode_dn(srv_dn_utf8
, 1);
2672 ldap_memfree(srv_dn_utf8
);
2674 return WERR_SERVER_UNAVAILABLE
;
2676 /* Now convert to CH_UNIX. */
2677 if (pull_utf8_allocate(&srv_dn
, srv_dn_utf8
) == (size_t)-1) {
2678 ldap_memfree(srv_dn_utf8
);
2679 ldap_memfree(srv_cn_utf8
);
2681 return WERR_SERVER_UNAVAILABLE
;
2683 if (pull_utf8_allocate(&srv_cn_0
, srv_cn_utf8
[0]) == (size_t)-1) {
2684 ldap_memfree(srv_dn_utf8
);
2685 ldap_memfree(srv_cn_utf8
);
2688 return WERR_SERVER_UNAVAILABLE
;
2691 ldap_memfree(srv_dn_utf8
);
2692 ldap_memfree(srv_cn_utf8
);
2694 asprintf(&prt_dn
, "cn=%s-%s,%s", srv_cn_0
,
2695 printer
->info_2
->sharename
, srv_dn
);
2698 SAFE_FREE(srv_cn_0
);
2700 /* build the ads mods */
2701 ctx
= talloc_init("nt_printer_publish_ads");
2702 mods
= ads_init_mods(ctx
);
2704 get_local_printer_publishing_data(ctx
, &mods
,
2705 &printer
->info_2
->data
);
2706 ads_mod_str(ctx
, &mods
, SPOOL_REG_PRINTERNAME
,
2707 printer
->info_2
->sharename
);
2710 ads_rc
= ads_add_printer_entry(ads
, prt_dn
, ctx
, &mods
);
2711 if (LDAP_ALREADY_EXISTS
== ads_rc
.err
.rc
)
2712 ads_rc
= ads_mod_printer_entry(ads
, prt_dn
, ctx
, &mods
);
2714 talloc_destroy(ctx
);
2716 /* retreive the guid and store it locally */
2717 if (ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
2719 ads_pull_guid(ads
, res
, &guid
);
2720 ads_msgfree(ads
, res
);
2721 store_printer_guid(printer
->info_2
, guid
);
2722 win_rc
= mod_a_printer(printer
, 2);
2729 static WERROR
nt_printer_unpublish_ads(ADS_STRUCT
*ads
,
2730 NT_PRINTER_INFO_LEVEL
*printer
)
2734 char *prt_dn
= NULL
;
2736 DEBUG(5, ("unpublishing printer %s\n", printer
->info_2
->printername
));
2738 /* remove the printer from the directory */
2739 ads_rc
= ads_find_printer_on_server(ads
, &res
,
2740 printer
->info_2
->sharename
, global_myname());
2742 if (ADS_ERR_OK(ads_rc
) && ads_count_replies(ads
, res
)) {
2743 prt_dn
= ads_get_dn(ads
, res
);
2744 ads_rc
= ads_del_dn(ads
, prt_dn
);
2745 ads_memfree(ads
, prt_dn
);
2748 ads_msgfree(ads
, res
);
2752 /****************************************************************************
2753 * Publish a printer in the directory
2755 * @param snum describing printer service
2756 * @return WERROR indicating status of publishing
2757 ***************************************************************************/
2759 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
2762 ADS_STRUCT
*ads
= NULL
;
2763 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2766 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
2767 if (!W_ERROR_IS_OK(win_rc
))
2771 case SPOOL_DS_PUBLISH
:
2772 case SPOOL_DS_UPDATE
:
2773 /* set the DsSpooler info and attributes */
2774 if (!(map_nt_printer_info2_to_dsspooler(printer
->info_2
))) {
2775 win_rc
= WERR_NOMEM
;
2779 printer
->info_2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
2781 case SPOOL_DS_UNPUBLISH
:
2782 printer
->info_2
->attributes
^= PRINTER_ATTRIBUTE_PUBLISHED
;
2785 win_rc
= WERR_NOT_SUPPORTED
;
2789 win_rc
= mod_a_printer(printer
, 2);
2790 if (!W_ERROR_IS_OK(win_rc
)) {
2791 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc
)));
2795 ads
= ads_init(NULL
, NULL
, NULL
);
2797 DEBUG(3, ("ads_init() failed\n"));
2798 win_rc
= WERR_SERVER_UNAVAILABLE
;
2801 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
2802 SAFE_FREE(ads
->auth
.password
);
2803 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
2806 /* ads_connect() will find the DC for us */
2807 ads_rc
= ads_connect(ads
);
2808 if (!ADS_ERR_OK(ads_rc
)) {
2809 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
2810 win_rc
= WERR_ACCESS_DENIED
;
2815 case SPOOL_DS_PUBLISH
:
2816 case SPOOL_DS_UPDATE
:
2817 win_rc
= nt_printer_publish_ads(ads
, printer
);
2819 case SPOOL_DS_UNPUBLISH
:
2820 win_rc
= nt_printer_unpublish_ads(ads
, printer
);
2825 free_a_printer(&printer
, 2);
2830 WERROR
check_published_printers(void)
2833 ADS_STRUCT
*ads
= NULL
;
2836 int n_services
= lp_numservices();
2837 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2840 ads
= ads_init(NULL
, NULL
, NULL
);
2842 DEBUG(3, ("ads_init() failed\n"));
2843 return WERR_SERVER_UNAVAILABLE
;
2845 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
2846 SAFE_FREE(ads
->auth
.password
);
2847 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
2850 /* ads_connect() will find the DC for us */
2851 ads_rc
= ads_connect(ads
);
2852 if (!ADS_ERR_OK(ads_rc
)) {
2853 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
2855 return WERR_ACCESS_DENIED
;
2858 for (snum
= 0; snum
< n_services
; snum
++) {
2859 if (!(lp_snum_ok(snum
) && lp_print_ok(snum
)))
2862 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2,
2863 lp_servicename(snum
))) ||
2864 !(printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
))
2867 DEBUG(5, ("checking directory for printer %s\n", printer
->info_2
->printername
));
2868 ads_rc
= ads_find_printer_on_server(ads
, &res
,
2869 printer
->info_2
->sharename
, global_myname());
2870 if (ADS_ERR_OK(ads_rc
) && ads_count_replies(ads
, res
)) {
2871 DEBUG(5, ("printer %s is in directory\n", printer
->info_2
->printername
));
2875 win_rc
= nt_printer_publish_ads(ads
, printer
);
2876 if (!W_ERROR_IS_OK(win_rc
))
2877 DEBUG(3, ("error publishing %s: %s\n", printer
->info_2
->sharename
, dos_errstr(win_rc
)));
2880 free_a_printer(&printer
, 2);
2881 ads_msgfree(ads
, res
);
2889 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
,
2892 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2894 REGISTRY_VALUE
*guid_val
;
2898 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
2900 if (!W_ERROR_IS_OK(win_rc
) ||
2901 !(printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) ||
2902 ((i
= lookup_printerkey(&printer
->info_2
->data
,
2903 SPOOL_DSSPOOLER_KEY
)) < 0) ||
2904 !(ctr
= &printer
->info_2
->data
.keys
[i
].values
) ||
2905 !(guid_val
= regval_ctr_getvalue(ctr
, "objectGUID"))) {
2906 free_a_printer(&printer
, 2);
2910 if (regval_size(guid_val
) == sizeof(struct uuid
))
2911 memcpy(guid
, regval_data_p(guid_val
), sizeof(struct uuid
));
2913 free_a_printer(&printer
, 2);
2917 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
2922 WERROR
check_published_printers(void)
2927 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
,
2932 #endif /* HAVE_ADS */
2934 /****************************************************************************
2935 ***************************************************************************/
2937 WERROR
delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
)
2939 NT_PRINTER_DATA
*data
;
2941 int removed_keys
= 0;
2945 empty_slot
= data
->num_keys
;
2948 return WERR_INVALID_PARAM
;
2950 /* remove all keys */
2952 if ( !strlen(key
) ) {
2953 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2954 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2955 data
->keys
[i
].name
));
2957 SAFE_FREE( data
->keys
[i
].name
);
2958 regval_ctr_destroy( &data
->keys
[i
].values
);
2961 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2964 SAFE_FREE( data
->keys
);
2965 ZERO_STRUCTP( data
);
2970 /* remove a specific key (and all subkeys) */
2972 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2973 if ( StrnCaseCmp( data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2974 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2975 data
->keys
[i
].name
));
2977 SAFE_FREE( data
->keys
[i
].name
);
2978 regval_ctr_destroy( &data
->keys
[i
].values
);
2980 /* mark the slot as empty */
2982 ZERO_STRUCTP( &data
->keys
[i
] );
2986 /* find the first empty slot */
2988 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2989 if ( !data
->keys
[i
].name
) {
2996 if ( i
== data
->num_keys
)
2997 /* nothing was removed */
2998 return WERR_INVALID_PARAM
;
3000 /* move everything down */
3002 for ( i
=empty_slot
+1; i
<data
->num_keys
; i
++ ) {
3003 if ( data
->keys
[i
].name
) {
3004 memcpy( &data
->keys
[empty_slot
], &data
->keys
[i
], sizeof(NT_PRINTER_KEY
) );
3005 ZERO_STRUCTP( &data
->keys
[i
] );
3013 data
->num_keys
-= removed_keys
;
3015 /* sanity check to see if anything is left */
3017 if ( !data
->num_keys
) {
3018 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2
->printername
));
3020 SAFE_FREE( data
->keys
);
3021 ZERO_STRUCTP( data
);
3027 /****************************************************************************
3028 ***************************************************************************/
3030 WERROR
delete_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3032 WERROR result
= WERR_OK
;
3035 /* we must have names on non-zero length */
3037 if ( !key
|| !*key
|| !value
|| !*value
)
3038 return WERR_INVALID_NAME
;
3040 /* find the printer key first */
3042 key_index
= lookup_printerkey( &p2
->data
, key
);
3043 if ( key_index
== -1 )
3046 /* make sure the value exists so we can return the correct error code */
3048 if ( !regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
) )
3049 return WERR_BADFILE
;
3051 regval_ctr_delvalue( &p2
->data
.keys
[key_index
].values
, value
);
3053 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3059 /****************************************************************************
3060 ***************************************************************************/
3062 WERROR
add_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
,
3063 uint32 type
, uint8
*data
, int real_len
)
3065 WERROR result
= WERR_OK
;
3068 /* we must have names on non-zero length */
3070 if ( !key
|| !*key
|| !value
|| !*value
)
3071 return WERR_INVALID_NAME
;
3073 /* find the printer key first */
3075 key_index
= lookup_printerkey( &p2
->data
, key
);
3076 if ( key_index
== -1 )
3077 key_index
= add_new_printer_key( &p2
->data
, key
);
3079 if ( key_index
== -1 )
3082 regval_ctr_addvalue( &p2
->data
.keys
[key_index
].values
, value
,
3083 type
, (const char *)data
, real_len
);
3085 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3086 key
, value
, type
, real_len
));
3091 /****************************************************************************
3092 ***************************************************************************/
3094 REGISTRY_VALUE
* get_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3098 if ( (key_index
= lookup_printerkey( &p2
->data
, key
)) == -1 )
3101 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3104 return regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
);
3107 /****************************************************************************
3108 Unpack a list of registry values frem the TDB
3109 ***************************************************************************/
3111 static int unpack_values(NT_PRINTER_DATA
*printer_data
, char *buf
, int buflen
)
3115 pstring string
, valuename
, keyname
;
3119 REGISTRY_VALUE
*regval_p
;
3122 /* add the "PrinterDriverData" key first for performance reasons */
3124 add_new_printer_key( printer_data
, SPOOL_PRINTERDATA_KEY
);
3126 /* loop and unpack the rest of the registry values */
3130 /* check to see if there are any more registry values */
3133 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", ®val_p
);
3137 /* unpack the next regval */
3139 len
+= tdb_unpack(buf
+len
, buflen
-len
, "fdB",
3146 * break of the keyname from the value name.
3147 * Valuenames can have embedded '\'s so be careful.
3148 * only support one level of keys. See the
3149 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3153 str
= strchr_m( string
, '\\');
3155 /* Put in "PrinterDriverData" is no key specified */
3158 pstrcpy( keyname
, SPOOL_PRINTERDATA_KEY
);
3159 pstrcpy( valuename
, string
);
3163 pstrcpy( keyname
, string
);
3164 pstrcpy( valuename
, str
+1 );
3167 /* see if we need a new key */
3169 if ( (key_index
=lookup_printerkey( printer_data
, keyname
)) == -1 )
3170 key_index
= add_new_printer_key( printer_data
, keyname
);
3172 if ( key_index
== -1 ) {
3173 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3178 /* add the new value */
3180 regval_ctr_addvalue( &printer_data
->keys
[key_index
].values
, valuename
, type
, (const char *)data_p
, size
);
3182 SAFE_FREE(data_p
); /* 'B' option to tdbpack does a malloc() */
3184 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname
, valuename
, size
));
3190 /****************************************************************************
3191 ***************************************************************************/
3193 static void map_to_os2_driver(fstring drivername
)
3195 static BOOL initialised
=False
;
3196 static fstring last_from
,last_to
;
3197 char *mapfile
= lp_os2_driver_map();
3198 char **lines
= NULL
;
3202 if (!strlen(drivername
))
3209 *last_from
= *last_to
= 0;
3213 if (strequal(drivername
,last_from
)) {
3214 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,last_to
));
3215 fstrcpy(drivername
,last_to
);
3219 lines
= file_lines_load(mapfile
, &numlines
);
3220 if (numlines
== 0) {
3221 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile
));
3225 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
3227 for( i
= 0; i
< numlines
; i
++) {
3228 char *nt_name
= lines
[i
];
3229 char *os2_name
= strchr(nt_name
,'=');
3236 while (isspace(*nt_name
))
3239 if (!*nt_name
|| strchr("#;",*nt_name
))
3243 int l
= strlen(nt_name
);
3244 while (l
&& isspace(nt_name
[l
-1])) {
3250 while (isspace(*os2_name
))
3254 int l
= strlen(os2_name
);
3255 while (l
&& isspace(os2_name
[l
-1])) {
3261 if (strequal(nt_name
,drivername
)) {
3262 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername
,os2_name
));
3263 fstrcpy(last_from
,drivername
);
3264 fstrcpy(last_to
,os2_name
);
3265 fstrcpy(drivername
,os2_name
);
3266 file_lines_free(lines
);
3271 file_lines_free(lines
);
3274 /****************************************************************************
3275 Get a default printer info 2 struct.
3276 ****************************************************************************/
3277 static WERROR
get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, const char *servername
, const char* sharename
)
3280 NT_PRINTER_INFO_LEVEL_2 info
;
3284 snum
= lp_servicenumber(sharename
);
3286 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", servername
);
3287 slprintf(info
.printername
, sizeof(info
.printername
)-1, "\\\\%s\\%s",
3288 servername
, sharename
);
3289 fstrcpy(info
.sharename
, sharename
);
3290 fstrcpy(info
.portname
, SAMBA_PRINTER_PORT_NAME
);
3292 /* by setting the driver name to an empty string, a local NT admin
3293 can now run the **local** APW to install a local printer driver
3294 for a Samba shared printer in 2.2. Without this, drivers **must** be
3295 installed on the Samba server for NT clients --jerry */
3296 #if 0 /* JERRY --do not uncomment-- */
3297 if (!*info
.drivername
)
3298 fstrcpy(info
.drivername
, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3302 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info
.drivername
));
3304 pstrcpy(info
.comment
, "");
3305 fstrcpy(info
.printprocessor
, "winprint");
3306 fstrcpy(info
.datatype
, "RAW");
3308 info
.attributes
= PRINTER_ATTRIBUTE_SAMBA
;
3310 info
.starttime
= 0; /* Minutes since 12:00am GMT */
3311 info
.untiltime
= 0; /* Minutes since 12:00am GMT */
3313 info
.default_priority
= 1;
3314 info
.setuptime
= (uint32
)time(NULL
);
3317 * I changed this as I think it is better to have a generic
3318 * DEVMODE than to crash Win2k explorer.exe --jerry
3319 * See the HP Deskjet 990c Win2k drivers for an example.
3321 * However the default devmode appears to cause problems
3322 * with the HP CLJ 8500 PCL driver. Hence the addition of
3323 * the "default devmode" parameter --jerry 22/01/2002
3326 if (lp_default_devmode(snum
)) {
3327 if ((info
.devmode
= construct_nt_devicemode(info
.printername
)) == NULL
)
3331 info
.devmode
= NULL
;
3334 /* This will get the current RPC talloc context, but we should be
3335 passing this as a parameter... fixme... JRA ! */
3337 if (!nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
))
3340 *info_ptr
= (NT_PRINTER_INFO_LEVEL_2
*)memdup(&info
, sizeof(info
));
3342 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3350 free_nt_devicemode(&info
.devmode
);
3351 return WERR_ACCESS_DENIED
;
3354 /****************************************************************************
3355 ****************************************************************************/
3356 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, const char *servername
, const char *sharename
)
3359 NT_PRINTER_INFO_LEVEL_2 info
;
3361 int snum
= lp_servicenumber(sharename
);
3362 TDB_DATA kbuf
, dbuf
;
3363 fstring printername
;
3364 char adevice
[MAXDEVICENAME
];
3368 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
3371 kbuf
.dsize
= strlen(key
)+1;
3373 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
3375 return get_a_printer_2_default(info_ptr
, servername
, sharename
);
3377 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "dddddddddddfffffPfffff",
3380 &info
.default_priority
,
3397 info
.printprocessor
,
3401 /* Samba has to have shared raw drivers. */
3402 info
.attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
3403 info
.attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
3405 /* Restore the stripped strings. */
3406 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", servername
);
3408 if ( lp_force_printername(snum
) )
3409 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, sharename
);
3411 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, info
.printername
);
3413 fstrcpy(info
.printername
, printername
);
3415 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3418 * Some client drivers freak out if there is a NULL devmode
3419 * (probably the driver is not checking before accessing
3420 * the devmode pointer) --jerry
3422 * See comments in get_a_printer_2_default()
3425 if (lp_default_devmode(snum
) && !info
.devmode
) {
3426 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3428 info
.devmode
= construct_nt_devicemode(printername
);
3431 safe_strcpy(adevice
, info
.printername
, sizeof(adevice
)-1);
3433 fstrcpy(info
.devmode
->devicename
, adevice
);
3436 len
+= unpack_values( &info
.data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3438 /* This will get the current RPC talloc context, but we should be
3439 passing this as a parameter... fixme... JRA ! */
3441 nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
);
3443 /* Fix for OS/2 drivers. */
3445 if (get_remote_arch() == RA_OS2
)
3446 map_to_os2_driver(info
.drivername
);
3448 SAFE_FREE(dbuf
.dptr
);
3449 *info_ptr
=memdup(&info
, sizeof(info
));
3451 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3452 sharename
, info
.printername
, info
.drivername
));
3457 /****************************************************************************
3458 Debugging function, dump at level 6 the struct in the logs.
3459 ****************************************************************************/
3460 static uint32
dump_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3463 NT_PRINTER_INFO_LEVEL_2
*info2
;
3465 DEBUG(106,("Dumping printer at level [%d]\n", level
));
3470 if (printer
->info_2
== NULL
)
3474 info2
=printer
->info_2
;
3476 DEBUGADD(106,("attributes:[%d]\n", info2
->attributes
));
3477 DEBUGADD(106,("priority:[%d]\n", info2
->priority
));
3478 DEBUGADD(106,("default_priority:[%d]\n", info2
->default_priority
));
3479 DEBUGADD(106,("starttime:[%d]\n", info2
->starttime
));
3480 DEBUGADD(106,("untiltime:[%d]\n", info2
->untiltime
));
3481 DEBUGADD(106,("status:[%d]\n", info2
->status
));
3482 DEBUGADD(106,("cjobs:[%d]\n", info2
->cjobs
));
3483 DEBUGADD(106,("averageppm:[%d]\n", info2
->averageppm
));
3484 DEBUGADD(106,("changeid:[%d]\n", info2
->changeid
));
3485 DEBUGADD(106,("c_setprinter:[%d]\n", info2
->c_setprinter
));
3486 DEBUGADD(106,("setuptime:[%d]\n", info2
->setuptime
));
3488 DEBUGADD(106,("servername:[%s]\n", info2
->servername
));
3489 DEBUGADD(106,("printername:[%s]\n", info2
->printername
));
3490 DEBUGADD(106,("sharename:[%s]\n", info2
->sharename
));
3491 DEBUGADD(106,("portname:[%s]\n", info2
->portname
));
3492 DEBUGADD(106,("drivername:[%s]\n", info2
->drivername
));
3493 DEBUGADD(106,("comment:[%s]\n", info2
->comment
));
3494 DEBUGADD(106,("location:[%s]\n", info2
->location
));
3495 DEBUGADD(106,("sepfile:[%s]\n", info2
->sepfile
));
3496 DEBUGADD(106,("printprocessor:[%s]\n", info2
->printprocessor
));
3497 DEBUGADD(106,("datatype:[%s]\n", info2
->datatype
));
3498 DEBUGADD(106,("parameters:[%s]\n", info2
->parameters
));
3504 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level
));
3512 /****************************************************************************
3513 Update the changeid time.
3514 This is SO NASTY as some drivers need this to change, others need it
3515 static. This value will change every second, and I must hope that this
3516 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3518 ****************************************************************************/
3520 static uint32
rev_changeid(void)
3524 get_process_uptime(&tv
);
3527 /* Return changeid as msec since spooler restart */
3528 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
3531 * This setting seems to work well but is too untested
3532 * to replace the above calculation. Left in for experiementation
3533 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3535 return tv
.tv_sec
* 10 + tv
.tv_usec
/ 100000;
3539 /********************************************************************
3540 Send a message to all smbds about the printer that just changed
3541 ********************************************************************/
3543 static BOOL
send_printer_mod_msg( char* printername
)
3545 int len
= strlen(printername
);
3550 DEBUG(10,("send_printer_mod_msg: Sending message about printer change [%s]\n",
3553 /* spam everyone that we just changed this printer */
3555 message_send_all( conn_tdb_ctx(), MSG_PRINTER_MOD
, printername
, len
+1, False
, NULL
);
3561 * The function below are the high level ones.
3562 * only those ones must be called from the spoolss code.
3566 /****************************************************************************
3567 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3568 ****************************************************************************/
3570 WERROR
mod_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3574 dump_a_printer(printer
, level
);
3577 * invalidate cache for all open handles to this printer.
3578 * cache for a given handle will be updated on the next
3582 invalidate_printer_hnd_cache( printer
->info_2
->sharename
);
3583 send_printer_mod_msg( printer
->info_2
->sharename
);
3589 * Update the changestamp. Emperical tests show that the
3590 * ChangeID is always updated,but c_setprinter is
3591 * global spooler variable (not per printer).
3594 /* ChangeID **must** be increasing over the lifetime
3595 of client's spoolss service in order for the
3596 client's cache to show updates */
3598 printer
->info_2
->changeid
= rev_changeid();
3601 * Because one day someone will ask:
3602 * NT->NT An admin connection to a remote
3603 * printer show changes imeediately in
3604 * the properities dialog
3606 * A non-admin connection will only show the
3607 * changes after viewing the properites page
3608 * 2 times. Seems to be related to a
3609 * race condition in the client between the spooler
3610 * updating the local cache and the Explorer.exe GUI
3611 * actually displaying the properties.
3613 * This is fixed in Win2k. admin/non-admin
3614 * connections both display changes immediately.
3619 result
=update_a_printer_2(printer
->info_2
);
3624 result
=WERR_UNKNOWN_LEVEL
;
3631 /****************************************************************************
3632 Initialize printer devmode & data with previously saved driver init values.
3633 ****************************************************************************/
3635 static BOOL
set_driver_init_2( NT_PRINTER_INFO_LEVEL_2
*info_ptr
)
3639 TDB_DATA kbuf
, dbuf
;
3640 NT_PRINTER_INFO_LEVEL_2 info
;
3646 * Delete any printer data 'values' already set. When called for driver
3647 * replace, there will generally be some, but during an add printer, there
3648 * should not be any (if there are delete them).
3651 delete_all_printer_data( info_ptr
, "" );
3653 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info_ptr
->drivername
);
3656 kbuf
.dsize
= strlen(key
)+1;
3658 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
3661 * When changing to a driver that has no init info in the tdb, remove
3662 * the previous drivers init info and leave the new on blank.
3664 free_nt_devicemode(&info_ptr
->devmode
);
3669 * Get the saved DEVMODE..
3672 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3675 * The saved DEVMODE contains the devicename from the printer used during
3676 * the initialization save. Change it to reflect the new printer.
3679 if ( info
.devmode
) {
3680 ZERO_STRUCT(info
.devmode
->devicename
);
3681 fstrcpy(info
.devmode
->devicename
, info_ptr
->printername
);
3685 * NT/2k does not change out the entire DeviceMode of a printer
3686 * when changing the driver. Only the driverextra, private, &
3687 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3689 * Later examination revealed that Windows NT/2k does reset the
3690 * the printer's device mode, bit **only** when you change a
3691 * property of the device mode such as the page orientation.
3696 /* Bind the saved DEVMODE to the new the printer */
3698 free_nt_devicemode(&info_ptr
->devmode
);
3699 info_ptr
->devmode
= info
.devmode
;
3701 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3702 info_ptr
->printername
, info_ptr
->devmode
?"VALID":"NULL", info_ptr
->drivername
));
3704 /* Add the printer data 'values' to the new printer */
3706 len
+= unpack_values( &info_ptr
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3709 SAFE_FREE(dbuf
.dptr
);
3714 /****************************************************************************
3715 Initialize printer devmode & data with previously saved driver init values.
3716 When a printer is created using AddPrinter, the drivername bound to the
3717 printer is used to lookup previously saved driver initialization info, which
3718 is bound to the new printer.
3719 ****************************************************************************/
3721 BOOL
set_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3723 BOOL result
= False
;
3727 result
= set_driver_init_2(printer
->info_2
);
3731 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3739 /****************************************************************************
3740 Delete driver init data stored for a specified driver
3741 ****************************************************************************/
3743 BOOL
del_driver_init(char *drivername
)
3748 if (!drivername
|| !*drivername
) {
3749 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3753 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, drivername
);
3756 kbuf
.dsize
= strlen(key
)+1;
3758 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername
));
3760 return (tdb_delete(tdb_drivers
, kbuf
) == 0);
3763 /****************************************************************************
3764 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3765 in the tdb. Note: this is different from the driver entry and the printer
3766 entry. There should be a single driver init entry for each driver regardless
3767 of whether it was installed from NT or 2K. Technically, they should be
3768 different, but they work out to the same struct.
3769 ****************************************************************************/
3771 static uint32
update_driver_init_2(NT_PRINTER_INFO_LEVEL_2
*info
)
3775 int buflen
, len
, ret
;
3776 TDB_DATA kbuf
, dbuf
;
3783 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
3785 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
3790 tb
= (char *)Realloc(buf
, len
);
3792 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3802 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info
->drivername
);
3805 kbuf
.dsize
= strlen(key
)+1;
3809 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
3813 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3817 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3818 info
->sharename
, info
->drivername
));
3823 /****************************************************************************
3824 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3825 ****************************************************************************/
3827 static uint32
update_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3831 dump_a_printer(printer
, level
);
3835 result
= update_driver_init_2(printer
->info_2
);
3845 /****************************************************************************
3846 Convert the printer data value, a REG_BINARY array, into an initialization
3847 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3848 got to keep the endians happy :).
3849 ****************************************************************************/
3851 static BOOL
convert_driver_init( TALLOC_CTX
*ctx
, NT_DEVICEMODE
*nt_devmode
, uint8
*data
, uint32 data_len
)
3853 BOOL result
= False
;
3857 ZERO_STRUCT(devmode
);
3859 prs_init(&ps
, 0, ctx
, UNMARSHALL
);
3860 ps
.data_p
= (char *)data
;
3861 ps
.buffer_size
= data_len
;
3863 if (spoolss_io_devmode("phantom DEVMODE", &ps
, 0, &devmode
))
3864 result
= convert_devicemode("", &devmode
, &nt_devmode
);
3866 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3871 /****************************************************************************
3872 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3874 1. Use the driver's config DLL to this UNC printername and:
3875 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3876 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3877 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3879 The last step triggers saving the "driver initialization" information for
3880 this printer into the tdb. Later, new printers that use this driver will
3881 have this initialization information bound to them. This simulates the
3882 driver initialization, as if it had run on the Samba server (as it would
3885 The Win32 client side code requirement sucks! But until we can run arbitrary
3886 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3888 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3889 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3890 about it and you will realize why. JRR 010720
3891 ****************************************************************************/
3893 static WERROR
save_driver_init_2(NT_PRINTER_INFO_LEVEL
*printer
, uint8
*data
, uint32 data_len
)
3895 WERROR status
= WERR_OK
;
3896 TALLOC_CTX
*ctx
= NULL
;
3897 NT_DEVICEMODE
*nt_devmode
= NULL
;
3898 NT_DEVICEMODE
*tmp_devmode
= printer
->info_2
->devmode
;
3901 * When the DEVMODE is already set on the printer, don't try to unpack it.
3903 DEBUG(8,("save_driver_init_2: Enter...\n"));
3905 if ( !printer
->info_2
->devmode
&& data_len
) {
3907 * Set devmode on printer info, so entire printer initialization can be
3911 if ((ctx
= talloc_init("save_driver_init_2")) == NULL
)
3914 if ((nt_devmode
= (NT_DEVICEMODE
*)malloc(sizeof(NT_DEVICEMODE
))) == NULL
) {
3915 status
= WERR_NOMEM
;
3919 ZERO_STRUCTP(nt_devmode
);
3922 * The DEVMODE is held in the 'data' component of the param in raw binary.
3923 * Convert it to to a devmode structure
3925 if ( !convert_driver_init( ctx
, nt_devmode
, data
, data_len
)) {
3926 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3927 status
= WERR_INVALID_PARAM
;
3931 printer
->info_2
->devmode
= nt_devmode
;
3935 * Pack up and add (or update) the DEVMODE and any current printer data to
3936 * a 'driver init' element in the tdb
3940 if ( update_driver_init(printer
, 2) != 0 ) {
3941 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3942 status
= WERR_NOMEM
;
3947 * If driver initialization info was successfully saved, set the current
3948 * printer to match it. This allows initialization of the current printer
3949 * as well as the driver.
3951 status
= mod_a_printer(printer
, 2);
3952 if (!W_ERROR_IS_OK(status
)) {
3953 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3954 printer
->info_2
->printername
));
3958 talloc_destroy(ctx
);
3959 free_nt_devicemode( &nt_devmode
);
3961 printer
->info_2
->devmode
= tmp_devmode
;
3966 /****************************************************************************
3967 Update the driver init info (DEVMODE and specifics) for a printer
3968 ****************************************************************************/
3970 WERROR
save_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
, uint8
*data
, uint32 data_len
)
3972 WERROR status
= WERR_OK
;
3976 status
= save_driver_init_2( printer
, data
, data_len
);
3979 status
= WERR_UNKNOWN_LEVEL
;
3986 /****************************************************************************
3987 Deep copy a NT_PRINTER_DATA
3988 ****************************************************************************/
3990 static NTSTATUS
copy_printer_data( NT_PRINTER_DATA
*dst
, NT_PRINTER_DATA
*src
)
3992 int i
, j
, num_vals
, new_key_index
;
3993 REGVAL_CTR
*src_key
, *dst_key
;
3996 return NT_STATUS_NO_MEMORY
;
3998 for ( i
=0; i
<src
->num_keys
; i
++ ) {
4000 /* create a new instance of the printerkey in the destination
4001 printer_data object */
4003 new_key_index
= add_new_printer_key( dst
, src
->keys
[i
].name
);
4004 dst_key
= &dst
->keys
[new_key_index
].values
;
4006 src_key
= &src
->keys
[i
].values
;
4007 num_vals
= regval_ctr_numvals( src_key
);
4009 /* dup the printer entire printer key */
4011 for ( j
=0; j
<num_vals
; j
++ ) {
4012 regval_ctr_copyvalue( dst_key
, regval_ctr_specific_value(src_key
, j
) );
4016 return NT_STATUS_OK
;
4019 /****************************************************************************
4020 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
4022 ****************************************************************************/
4024 NT_PRINTER_INFO_LEVEL_2
* dup_printer_2( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL_2
*printer
)
4026 NT_PRINTER_INFO_LEVEL_2
*copy
;
4031 if ( !(copy
= (NT_PRINTER_INFO_LEVEL_2
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2
))) )
4034 memcpy( copy
, printer
, sizeof(NT_PRINTER_INFO_LEVEL_2
) );
4036 /* malloc()'d members copied here */
4038 copy
->devmode
= dup_nt_devicemode( printer
->devmode
);
4040 ZERO_STRUCT( copy
->data
);
4041 copy_printer_data( ©
->data
, &printer
->data
);
4043 /* this is talloc()'d; very ugly that we have a structure that
4044 is half malloc()'d and half talloc()'d but that is the way
4045 that the PRINTER_INFO stuff is written right now. --jerry */
4047 copy
->secdesc_buf
= dup_sec_desc_buf( ctx
, printer
->secdesc_buf
);
4052 /****************************************************************************
4053 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4055 Previously the code had a memory allocation problem because it always
4056 used the TALLOC_CTX from the Printer_entry*. This context lasts
4057 as a long as the original handle is open. So if the client made a lot
4058 of getprinter[data]() calls, the memory usage would climb. Now we use
4059 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4060 still use the Printer_entry->ctx for maintaining the cache copy though
4061 since that object must live as long as the handle by definition.
4064 ****************************************************************************/
4066 WERROR
get_a_printer( Printer_entry
*print_hnd
, NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
,
4067 const char *sharename
)
4070 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4075 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename
, (unsigned int)level
));
4079 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
4080 DEBUG(0,("get_a_printer: malloc fail.\n"));
4083 ZERO_STRUCTP(printer
);
4086 fstrcpy( servername
, print_hnd
->servername
);
4088 fstrcpy( servername
, "%L" );
4089 standard_sub_basic( "", servername
, sizeof(servername
)-1 );
4093 * check for cache first. A Printer handle cannot changed
4094 * to another printer object so we only check that the printer
4095 * is actually for a printer and that the printer_info pointer
4099 && (print_hnd
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)
4100 && print_hnd
->printer_info
)
4102 /* get_talloc_ctx() works here because we need a short
4103 lived talloc context */
4105 if ( !(printer
->info_2
= dup_printer_2(get_talloc_ctx(), print_hnd
->printer_info
->info_2
)) )
4107 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
4113 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
4115 *pp_printer
= printer
;
4121 /* no cache for this handle; see if we can match one from another handle.
4122 Make sure to use a short lived talloc ctx */
4125 result
= find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer
->info_2
, servername
, sharename
);
4127 /* fail to disk if we don't have it with any open handle */
4129 if ( !print_hnd
|| !W_ERROR_IS_OK(result
) )
4130 result
= get_a_printer_2(&printer
->info_2
, servername
, sharename
);
4132 /* we have a new printer now. Save it with this handle */
4134 if ( W_ERROR_IS_OK(result
) ) {
4135 dump_a_printer(printer
, level
);
4137 /* save a copy in cache */
4138 if ( print_hnd
&& (print_hnd
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)) {
4139 if ( !print_hnd
->printer_info
)
4140 print_hnd
->printer_info
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
));
4142 if ( print_hnd
->printer_info
) {
4143 /* make sure to use the handle's talloc ctx here since
4144 the printer_2 object must last until the handle is closed */
4146 print_hnd
->printer_info
->info_2
= dup_printer_2(print_hnd
->ctx
, printer
->info_2
);
4148 /* don't fail the lookup just because the cache update failed */
4149 if ( !print_hnd
->printer_info
->info_2
)
4150 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4153 *pp_printer
= printer
;
4161 result
=WERR_UNKNOWN_LEVEL
;
4165 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename
, (unsigned int)level
, dos_errstr(result
)));
4170 /****************************************************************************
4171 Deletes a NT_PRINTER_INFO_LEVEL struct.
4172 ****************************************************************************/
4174 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
4177 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
4179 DEBUG(104,("freeing a printer at level [%d]\n", level
));
4181 if (printer
== NULL
)
4186 if (printer
->info_2
!= NULL
) {
4187 free_nt_printer_info_level_2(&printer
->info_2
);
4198 SAFE_FREE(*pp_printer
);
4202 /****************************************************************************
4203 ****************************************************************************/
4204 uint32
add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4207 DEBUG(104,("adding a printer at level [%d]\n", level
));
4208 dump_a_printer_driver(driver
, level
);
4212 result
=add_a_printer_driver_3(driver
.info_3
);
4216 result
=add_a_printer_driver_6(driver
.info_6
);
4226 /****************************************************************************
4227 ****************************************************************************/
4229 WERROR
get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL
*driver
, uint32 level
,
4230 fstring drivername
, const char *architecture
, uint32 version
)
4236 /* Sometime we just want any version of the driver */
4238 if ( version
== DRIVER_ANY_VERSION
) {
4239 /* look for Win2k first and then for NT4 */
4240 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4243 if ( !W_ERROR_IS_OK(result
) ) {
4244 result
= get_a_printer_driver_3( &driver
->info_3
,
4245 drivername
, architecture
, 2 );
4248 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4249 architecture
, version
);
4258 if (W_ERROR_IS_OK(result
))
4259 dump_a_printer_driver(*driver
, level
);
4264 /****************************************************************************
4265 ****************************************************************************/
4266 uint32
free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4273 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
4274 if (driver
.info_3
!= NULL
)
4276 info3
=driver
.info_3
;
4277 SAFE_FREE(info3
->dependentfiles
);
4278 ZERO_STRUCTP(info3
);
4288 NT_PRINTER_DRIVER_INFO_LEVEL_6
*info6
;
4289 if (driver
.info_6
!= NULL
) {
4290 info6
=driver
.info_6
;
4291 SAFE_FREE(info6
->dependentfiles
);
4292 SAFE_FREE(info6
->previousnames
);
4293 ZERO_STRUCTP(info6
);
4309 /****************************************************************************
4310 Determine whether or not a particular driver is currently assigned
4312 ****************************************************************************/
4314 BOOL
printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
)
4317 int n_services
= lp_numservices();
4318 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4323 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4325 /* loop through the printers.tdb and check for the drivername */
4327 for (snum
=0; snum
<n_services
; snum
++) {
4328 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
4331 if ( !W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))) )
4334 if ( !StrCaseCmp(info_3
->name
, printer
->info_2
->drivername
) ) {
4335 free_a_printer( &printer
, 2 );
4339 free_a_printer( &printer
, 2 );
4342 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4344 /* report that the driver is not in use by default */
4350 /**********************************************************************
4351 Check to see if a ogiven file is in use by *info
4352 *********************************************************************/
4354 static BOOL
drv_file_in_use( char* file
, NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4361 if ( strequal(file
, info
->driverpath
) )
4364 if ( strequal(file
, info
->datafile
) )
4367 if ( strequal(file
, info
->configfile
) )
4370 if ( strequal(file
, info
->helpfile
) )
4373 /* see of there are any dependent files to examine */
4375 if ( !info
->dependentfiles
)
4378 while ( *info
->dependentfiles
[i
] ) {
4379 if ( strequal(file
, info
->dependentfiles
[i
]) )
4388 /**********************************************************************
4389 Utility function to remove the dependent file pointed to by the
4390 input parameter from the list
4391 *********************************************************************/
4393 static void trim_dependent_file( fstring files
[], int idx
)
4396 /* bump everything down a slot */
4398 while( *files
[idx
+1] ) {
4399 fstrcpy( files
[idx
], files
[idx
+1] );
4408 /**********************************************************************
4409 Check if any of the files used by src are also used by drv
4410 *********************************************************************/
4412 static BOOL
trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*src
,
4413 NT_PRINTER_DRIVER_INFO_LEVEL_3
*drv
)
4415 BOOL in_use
= False
;
4421 /* check each file. Remove it from the src structure if it overlaps */
4423 if ( drv_file_in_use(src
->driverpath
, drv
) ) {
4425 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driverpath
));
4426 fstrcpy( src
->driverpath
, "" );
4429 if ( drv_file_in_use(src
->datafile
, drv
) ) {
4431 DEBUG(10,("Removing datafile [%s] from list\n", src
->datafile
));
4432 fstrcpy( src
->datafile
, "" );
4435 if ( drv_file_in_use(src
->configfile
, drv
) ) {
4437 DEBUG(10,("Removing configfile [%s] from list\n", src
->configfile
));
4438 fstrcpy( src
->configfile
, "" );
4441 if ( drv_file_in_use(src
->helpfile
, drv
) ) {
4443 DEBUG(10,("Removing helpfile [%s] from list\n", src
->helpfile
));
4444 fstrcpy( src
->helpfile
, "" );
4447 /* are there any dependentfiles to examine? */
4449 if ( !src
->dependentfiles
)
4452 while ( *src
->dependentfiles
[i
] ) {
4453 if ( drv_file_in_use(src
->dependentfiles
[i
], drv
) ) {
4455 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependentfiles
[i
]));
4456 trim_dependent_file( src
->dependentfiles
, i
);
4464 /****************************************************************************
4465 Determine whether or not a particular driver files are currently being
4466 used by any other driver.
4468 Return value is True if any files were in use by other drivers
4469 and False otherwise.
4471 Upon return, *info has been modified to only contain the driver files
4472 which are not in use
4473 ****************************************************************************/
4475 BOOL
printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4480 fstring
*list
= NULL
;
4481 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4486 version
= info
->cversion
;
4488 /* loop over all driver versions */
4490 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4492 /* get the list of drivers */
4495 ndrivers
= get_ntdrivers(&list
, info
->environment
, version
);
4497 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4498 ndrivers
, info
->environment
, version
));
4500 /* check each driver for overlap in files */
4502 for (i
=0; i
<ndrivers
; i
++) {
4503 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
4505 ZERO_STRUCT(driver
);
4507 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, list
[i
], info
->environment
, version
)) ) {
4512 /* check if d2 uses any files from d1 */
4513 /* only if this is a different driver than the one being deleted */
4515 if ( !strequal(info
->name
, driver
.info_3
->name
) ) {
4516 if ( trim_overlap_drv_files(info
, driver
.info_3
) ) {
4517 free_a_printer_driver(driver
, 3);
4523 free_a_printer_driver(driver
, 3);
4528 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4530 driver
.info_3
= info
;
4532 if ( DEBUGLEVEL
>= 20 )
4533 dump_a_printer_driver( driver
, 3 );
4538 /****************************************************************************
4539 Actually delete the driver files. Make sure that
4540 printer_driver_files_in_use() return False before calling
4542 ****************************************************************************/
4544 static BOOL
delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
)
4548 connection_struct
*conn
;
4558 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3
->name
, info_3
->cversion
));
4561 * Connect to the print$ share under the same account as the
4562 * user connected to the rpc pipe. Note we must be root to
4566 null_pw
= data_blob( NULL
, 0 );
4567 fstrcpy(res_type
, "A:");
4569 conn
= make_connection_with_chdir( "print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
4573 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4577 /* Save who we are - we are temporarily becoming the connection user. */
4579 if ( !become_user(conn
, conn
->vuid
) ) {
4580 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4584 /* now delete the files; must strip the '\print$' string from
4587 if ( *info_3
->driverpath
) {
4588 if ( (s
= strchr( &info_3
->driverpath
[1], '\\' )) != NULL
) {
4589 driver_unix_convert(s
, conn
, NULL
, &bad_path
, &st
);
4590 DEBUG(10,("deleting driverfile [%s]\n", s
));
4591 unlink_internals(conn
, 0, s
);
4595 if ( *info_3
->configfile
) {
4596 if ( (s
= strchr( &info_3
->configfile
[1], '\\' )) != NULL
) {
4597 driver_unix_convert(s
, conn
, NULL
, &bad_path
, &st
);
4598 DEBUG(10,("deleting configfile [%s]\n", s
));
4599 unlink_internals(conn
, 0, s
);
4603 if ( *info_3
->datafile
) {
4604 if ( (s
= strchr( &info_3
->datafile
[1], '\\' )) != NULL
) {
4605 driver_unix_convert(s
, conn
, NULL
, &bad_path
, &st
);
4606 DEBUG(10,("deleting datafile [%s]\n", s
));
4607 unlink_internals(conn
, 0, s
);
4611 if ( *info_3
->helpfile
) {
4612 if ( (s
= strchr( &info_3
->helpfile
[1], '\\' )) != NULL
) {
4613 driver_unix_convert(s
, conn
, NULL
, &bad_path
, &st
);
4614 DEBUG(10,("deleting helpfile [%s]\n", s
));
4615 unlink_internals(conn
, 0, s
);
4619 /* check if we are done removing files */
4621 if ( info_3
->dependentfiles
) {
4622 while ( *info_3
->dependentfiles
[i
] ) {
4625 /* bypass the "\print$" portion of the path */
4627 if ( (file
= strchr( info_3
->dependentfiles
[i
]+1, '\\' )) != NULL
) {
4628 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4629 DEBUG(10,("deleting dependent file [%s]\n", file
));
4630 unlink_internals(conn
, 0, file
);
4642 /****************************************************************************
4643 Remove a printer driver from the TDB. This assumes that the the driver was
4644 previously looked up.
4645 ***************************************************************************/
4647 WERROR
delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
,
4648 uint32 version
, BOOL delete_files
)
4652 TDB_DATA kbuf
, dbuf
;
4653 NT_PRINTER_DRIVER_INFO_LEVEL ctr
;
4655 /* delete the tdb data first */
4657 arch
= get_short_archi(info_3
->environment
);
4658 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
,
4659 arch
, version
, info_3
->name
);
4661 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4662 key
, delete_files
? "TRUE" : "FALSE" ));
4664 ctr
.info_3
= info_3
;
4665 dump_a_printer_driver( ctr
, 3 );
4668 kbuf
.dsize
=strlen(key
)+1;
4670 /* check if the driver actually exists for this environment */
4672 dbuf
= tdb_fetch( tdb_drivers
, kbuf
);
4674 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key
));
4675 return WERR_UNKNOWN_PRINTER_DRIVER
;
4678 SAFE_FREE( dbuf
.dptr
);
4680 /* ok... the driver exists so the delete should return success */
4682 if (tdb_delete(tdb_drivers
, kbuf
) == -1) {
4683 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key
));
4684 return WERR_ACCESS_DENIED
;
4688 * now delete any associated files if delete_files == True
4689 * even if this part failes, we return succes because the
4690 * driver doesn not exist any more
4694 delete_driver_files( info_3
, user
);
4697 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key
));
4702 /****************************************************************************
4703 Store a security desc for a printer.
4704 ****************************************************************************/
4706 WERROR
nt_printing_setsec(const char *printername
, SEC_DESC_BUF
*secdesc_ctr
)
4708 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4709 SEC_DESC_BUF
*old_secdesc_ctr
= NULL
;
4711 TALLOC_CTX
*mem_ctx
= NULL
;
4715 mem_ctx
= talloc_init("nt_printing_setsec");
4716 if (mem_ctx
== NULL
)
4719 /* The old owner and group sids of the security descriptor are not
4720 present when new ACEs are added or removed by changing printer
4721 permissions through NT. If they are NULL in the new security
4722 descriptor then copy them over from the old one. */
4724 if (!secdesc_ctr
->sec
->owner_sid
|| !secdesc_ctr
->sec
->grp_sid
) {
4725 DOM_SID
*owner_sid
, *group_sid
;
4726 SEC_ACL
*dacl
, *sacl
;
4727 SEC_DESC
*psd
= NULL
;
4730 nt_printing_getsec(mem_ctx
, printername
, &old_secdesc_ctr
);
4732 /* Pick out correct owner and group sids */
4734 owner_sid
= secdesc_ctr
->sec
->owner_sid
?
4735 secdesc_ctr
->sec
->owner_sid
:
4736 old_secdesc_ctr
->sec
->owner_sid
;
4738 group_sid
= secdesc_ctr
->sec
->grp_sid
?
4739 secdesc_ctr
->sec
->grp_sid
:
4740 old_secdesc_ctr
->sec
->grp_sid
;
4742 dacl
= secdesc_ctr
->sec
->dacl
?
4743 secdesc_ctr
->sec
->dacl
:
4744 old_secdesc_ctr
->sec
->dacl
;
4746 sacl
= secdesc_ctr
->sec
->sacl
?
4747 secdesc_ctr
->sec
->sacl
:
4748 old_secdesc_ctr
->sec
->sacl
;
4750 /* Make a deep copy of the security descriptor */
4752 psd
= make_sec_desc(mem_ctx
, secdesc_ctr
->sec
->revision
, secdesc_ctr
->sec
->type
,
4753 owner_sid
, group_sid
,
4758 new_secdesc_ctr
= make_sec_desc_buf(mem_ctx
, size
, psd
);
4761 if (!new_secdesc_ctr
) {
4762 new_secdesc_ctr
= secdesc_ctr
;
4765 /* Store the security descriptor in a tdb */
4767 prs_init(&ps
, (uint32
)sec_desc_size(new_secdesc_ctr
->sec
) +
4768 sizeof(SEC_DESC_BUF
), mem_ctx
, MARSHALL
);
4770 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr
,
4772 status
= WERR_BADFUNC
;
4776 slprintf(key
, sizeof(key
)-1, "SECDESC/%s", printername
);
4778 if (tdb_prs_store(tdb_printers
, key
, &ps
)==0) {
4781 DEBUG(1,("Failed to store secdesc for %s\n", printername
));
4782 status
= WERR_BADFUNC
;
4785 /* Free malloc'ed memory */
4791 talloc_destroy(mem_ctx
);
4795 /****************************************************************************
4796 Construct a default security descriptor buffer for a printer.
4797 ****************************************************************************/
4799 static SEC_DESC_BUF
*construct_default_printer_sdb(TALLOC_CTX
*ctx
)
4803 SEC_ACL
*psa
= NULL
;
4804 SEC_DESC_BUF
*sdb
= NULL
;
4805 SEC_DESC
*psd
= NULL
;
4809 /* Create an ACE where Everyone is allowed to print */
4811 init_sec_access(&sa
, PRINTER_ACE_PRINT
);
4812 init_sec_ace(&ace
[0], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4813 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4815 /* Make the security descriptor owned by the Administrators group
4816 on the PDC of the domain. */
4818 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
4819 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4822 /* Backup plan - make printer owned by admins.
4823 This should emulate a lanman printer as security
4824 settings can't be changed. */
4826 sid_copy(&owner_sid
, get_global_sam_sid());
4827 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4830 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
4831 init_sec_ace(&ace
[1], &owner_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4832 sa
, SEC_ACE_FLAG_OBJECT_INHERIT
|
4833 SEC_ACE_FLAG_INHERIT_ONLY
);
4835 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
4836 init_sec_ace(&ace
[2], &owner_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4837 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4839 /* The ACL revision number in rpc_secdesc.h differs from the one
4840 created by NT when setting ACE entries in printer
4841 descriptors. NT4 complains about the property being edited by a
4844 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, 3, ace
)) != NULL
) {
4845 psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
4847 NULL
, psa
, &sd_size
);
4851 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4855 sdb
= make_sec_desc_buf(ctx
, sd_size
, psd
);
4857 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4858 (unsigned int)sd_size
));
4863 /****************************************************************************
4864 Get a security desc for a printer.
4865 ****************************************************************************/
4867 BOOL
nt_printing_getsec(TALLOC_CTX
*ctx
, const char *printername
, SEC_DESC_BUF
**secdesc_ctr
)
4873 if (strlen(printername
) > 2 && (temp
= strchr(printername
+ 2, '\\'))) {
4874 printername
= temp
+ 1;
4877 /* Fetch security descriptor from tdb */
4879 slprintf(key
, sizeof(key
)-1, "SECDESC/%s", printername
);
4881 if (tdb_prs_fetch(tdb_printers
, key
, &ps
, ctx
)!=0 ||
4882 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1)) {
4884 DEBUG(4,("using default secdesc for %s\n", printername
));
4886 if (!(*secdesc_ctr
= construct_default_printer_sdb(ctx
))) {
4890 /* Save default security descriptor for later */
4892 prs_init(&ps
, (uint32
)sec_desc_size((*secdesc_ctr
)->sec
) +
4893 sizeof(SEC_DESC_BUF
), ctx
, MARSHALL
);
4895 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1))
4896 tdb_prs_store(tdb_printers
, key
, &ps
);
4903 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4904 this security descriptor has been created when winbindd was
4905 down. Take ownership of security descriptor. */
4907 if (sid_equal((*secdesc_ctr
)->sec
->owner_sid
, &global_sid_World
)) {
4910 /* Change sd owner to workgroup administrator */
4912 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
4913 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4914 SEC_DESC
*psd
= NULL
;
4919 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
4921 psd
= make_sec_desc(ctx
, (*secdesc_ctr
)->sec
->revision
, (*secdesc_ctr
)->sec
->type
,
4923 (*secdesc_ctr
)->sec
->grp_sid
,
4924 (*secdesc_ctr
)->sec
->sacl
,
4925 (*secdesc_ctr
)->sec
->dacl
,
4928 new_secdesc_ctr
= make_sec_desc_buf(ctx
, size
, psd
);
4930 /* Swap with other one */
4932 *secdesc_ctr
= new_secdesc_ctr
;
4936 nt_printing_setsec(printername
, *secdesc_ctr
);
4940 if (DEBUGLEVEL
>= 10) {
4941 SEC_ACL
*the_acl
= (*secdesc_ctr
)->sec
->dacl
;
4944 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4945 printername
, the_acl
->num_aces
));
4947 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4950 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
4952 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str
,
4953 the_acl
->ace
[i
].type
, the_acl
->ace
[i
].flags
,
4954 the_acl
->ace
[i
].info
.mask
));
4964 1: level not implemented
4965 2: file doesn't exist
4966 3: can't allocate memory
4967 4: can't free memory
4968 5: non existant struct
4972 A printer and a printer driver are 2 different things.
4973 NT manages them separatelly, Samba does the same.
4974 Why ? Simply because it's easier and it makes sense !
4976 Now explanation: You have 3 printers behind your samba server,
4977 2 of them are the same make and model (laser A and B). But laser B
4978 has an 3000 sheet feeder and laser A doesn't such an option.
4979 Your third printer is an old dot-matrix model for the accounting :-).
4981 If the /usr/local/samba/lib directory (default dir), you will have
4982 5 files to describe all of this.
4984 3 files for the printers (1 by printer):
4987 NTprinter_accounting
4988 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4989 NTdriver_printer model X
4990 NTdriver_printer model Y
4992 jfm: I should use this comment for the text file to explain
4993 same thing for the forms BTW.
4994 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4998 /* Convert generic access rights to printer object specific access rights.
4999 It turns out that NT4 security descriptors use generic access rights and
5000 NT5 the object specific ones. */
5002 void map_printer_permissions(SEC_DESC
*sd
)
5006 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
5007 se_map_generic(&sd
->dacl
->ace
[i
].info
.mask
,
5008 &printer_generic_mapping
);
5012 /****************************************************************************
5013 Check a user has permissions to perform the given operation. We use the
5014 permission constants defined in include/rpc_spoolss.h to check the various
5015 actions we perform when checking printer access.
5017 PRINTER_ACCESS_ADMINISTER:
5018 print_queue_pause, print_queue_resume, update_printer_sec,
5019 update_printer, spoolss_addprinterex_level_2,
5020 _spoolss_setprinterdata
5025 JOB_ACCESS_ADMINISTER:
5026 print_job_delete, print_job_pause, print_job_resume,
5029 ****************************************************************************/
5030 BOOL
print_access_check(struct current_user
*user
, int snum
, int access_type
)
5032 SEC_DESC_BUF
*secdesc
= NULL
;
5033 uint32 access_granted
;
5037 TALLOC_CTX
*mem_ctx
= NULL
;
5038 extern struct current_user current_user
;
5040 /* If user is NULL then use the current_user structure */
5043 user
= ¤t_user
;
5045 /* Always allow root or printer admins to do anything */
5047 if (user
->uid
== 0 ||
5048 user_in_list(uidtoname(user
->uid
), lp_printer_admin(snum
), user
->groups
, user
->ngroups
)) {
5052 /* Get printer name */
5054 pname
= PRINTERNAME(snum
);
5056 if (!pname
|| !*pname
) {
5061 /* Get printer security descriptor */
5063 if(!(mem_ctx
= talloc_init("print_access_check"))) {
5068 nt_printing_getsec(mem_ctx
, pname
, &secdesc
);
5070 if (access_type
== JOB_ACCESS_ADMINISTER
) {
5071 SEC_DESC_BUF
*parent_secdesc
= secdesc
;
5073 /* Create a child security descriptor to check permissions
5074 against. This is because print jobs are child objects
5075 objects of a printer. */
5077 secdesc
= se_create_child_secdesc(mem_ctx
, parent_secdesc
->sec
, False
);
5079 /* Now this is the bit that really confuses me. The access
5080 type needs to be changed from JOB_ACCESS_ADMINISTER to
5081 PRINTER_ACCESS_ADMINISTER for this to work. Something
5082 to do with the child (job) object becoming like a
5085 access_type
= PRINTER_ACCESS_ADMINISTER
;
5090 map_printer_permissions(secdesc
->sec
);
5092 result
= se_access_check(secdesc
->sec
, user
->nt_user_token
, access_type
,
5093 &access_granted
, &status
);
5095 DEBUG(4, ("access check was %s\n", result
? "SUCCESS" : "FAILURE"));
5097 talloc_destroy(mem_ctx
);
5105 /****************************************************************************
5106 Check the time parameters allow a print operation.
5107 *****************************************************************************/
5109 BOOL
print_time_access_check(int snum
)
5111 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5113 time_t now
= time(NULL
);
5117 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))))
5120 if (printer
->info_2
->starttime
== 0 && printer
->info_2
->untiltime
== 0)
5124 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
5126 if (mins
>= printer
->info_2
->starttime
&& mins
<= printer
->info_2
->untiltime
)
5129 free_a_printer(&printer
, 2);
5137 /****************************************************************************
5138 Fill in the servername sent in the _spoolss_open_printer_ex() call
5139 ****************************************************************************/
5140 char* get_server_name( Printer_entry
*printer
)
5142 return printer
->servername
;