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 struct current_user current_user
;
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 */
41 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
43 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_4
45 /* Map generic permissions to printer object specific permissions */
47 GENERIC_MAPPING printer_generic_mapping
= {
54 STANDARD_MAPPING printer_std_mapping
= {
61 /* Map generic permissions to print server object specific permissions */
63 GENERIC_MAPPING printserver_generic_mapping
= {
70 STANDARD_MAPPING printserver_std_mapping
= {
77 /* We need one default form to support our default printer. Msoft adds the
78 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
79 array index). Letter is always first, so (for the current code) additions
80 always put things in the correct order. */
81 static const nt_forms_struct default_forms
[] = {
82 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
84 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
85 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
86 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
87 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
88 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
89 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
90 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
92 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
93 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
94 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
95 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
96 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
97 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
98 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
99 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
100 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
101 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
102 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
103 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
104 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
105 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
106 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
107 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
108 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
109 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
110 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
111 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
112 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
113 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
114 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
115 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
116 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
117 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
118 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
119 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
120 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
121 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
122 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
123 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
124 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
125 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
126 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
127 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
128 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
129 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
131 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
132 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
133 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
134 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
135 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
136 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
137 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
138 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
139 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
140 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
141 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
142 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
143 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
144 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
145 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
146 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
147 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
148 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
149 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
150 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
151 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
152 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
153 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
154 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
155 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
156 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
157 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
158 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
159 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
160 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
161 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
162 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
163 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
164 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
165 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
166 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
167 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
168 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
169 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
170 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
171 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
172 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
173 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
174 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
175 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
176 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
177 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
178 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
179 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
180 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
181 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
182 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
183 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
184 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
185 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
186 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
187 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
188 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
189 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
190 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
191 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
192 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
193 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
194 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
195 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
196 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
197 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
198 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
199 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
203 const char *long_archi
;
204 const char *short_archi
;
208 #define SPL_ARCH_WIN40 "WIN40"
209 #define SPL_ARCH_W32X86 "W32X86"
210 #define SPL_ARCH_W32MIPS "W32MIPS"
211 #define SPL_ARCH_W32ALPHA "W32ALPHA"
212 #define SPL_ARCH_W32PPC "W32PPC"
213 #define SPL_ARCH_IA64 "IA64"
214 #define SPL_ARCH_X64 "x64"
216 static const struct table_node archi_table
[]= {
218 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
219 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
220 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
221 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
222 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
223 {"Windows IA64", SPL_ARCH_IA64
, 3 },
224 {"Windows x64", SPL_ARCH_X64
, 3 },
228 static BOOL
upgrade_to_version_3(void)
230 TDB_DATA kbuf
, newkey
, dbuf
;
232 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
234 for (kbuf
= tdb_firstkey(tdb_drivers
); kbuf
.dptr
;
235 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
237 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
239 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) == 0) {
240 DEBUG(0,("upgrade_to_version_3:moving form\n"));
241 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
242 SAFE_FREE(dbuf
.dptr
);
243 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms
)));
246 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
247 SAFE_FREE(dbuf
.dptr
);
248 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
253 if (strncmp(kbuf
.dptr
, PRINTERS_PREFIX
, strlen(PRINTERS_PREFIX
)) == 0) {
254 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
255 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
256 SAFE_FREE(dbuf
.dptr
);
257 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers
)));
260 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
261 SAFE_FREE(dbuf
.dptr
);
262 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
267 if (strncmp(kbuf
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
)) == 0) {
268 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
269 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
270 SAFE_FREE(dbuf
.dptr
);
271 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers
)));
274 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
275 SAFE_FREE(dbuf
.dptr
);
276 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
281 SAFE_FREE(dbuf
.dptr
);
287 /*******************************************************************
288 Fix an issue with security descriptors. Printer sec_desc must
289 use more than the generic bits that were previously used
290 in <= 3.0.14a. They must also have a owner and group SID assigned.
291 Otherwise, any printers than have been migrated to a Windows
292 host using printmig.exe will not be accessible.
293 *******************************************************************/
295 static int sec_desc_upg_fn( TDB_CONTEXT
*the_tdb
, TDB_DATA key
,
296 TDB_DATA data
, void *state
)
299 SEC_DESC_BUF
*sd_orig
= NULL
;
300 SEC_DESC_BUF
*sd_new
, *sd_store
;
301 SEC_DESC
*sec
, *new_sec
;
302 TALLOC_CTX
*ctx
= state
;
304 uint32 sd_size
, size_new_sec
;
307 if (!data
.dptr
|| data
.dsize
== 0)
310 if ( strncmp( key
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
) ) != 0 )
313 /* upgrade the security descriptor */
317 prs_init( &ps
, 0, ctx
, UNMARSHALL
);
318 prs_give_memory( &ps
, data
.dptr
, data
.dsize
, True
);
320 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig
, &ps
, 1 ) ) {
321 /* delete bad entries */
322 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n", key
.dptr
));
323 tdb_delete( tdb_printers
, key
);
329 /* is this even valid? */
334 /* update access masks */
336 for ( i
=0; i
<sec
->dacl
->num_aces
; i
++ ) {
337 switch ( sec
->dacl
->ace
[i
].info
.mask
) {
338 case (GENERIC_READ_ACCESS
| GENERIC_WRITE_ACCESS
| GENERIC_EXECUTE_ACCESS
):
339 sec
->dacl
->ace
[i
].info
.mask
= PRINTER_ACE_PRINT
;
342 case GENERIC_ALL_ACCESS
:
343 sec
->dacl
->ace
[i
].info
.mask
= PRINTER_ACE_FULL_CONTROL
;
346 case READ_CONTROL_ACCESS
:
347 sec
->dacl
->ace
[i
].info
.mask
= PRINTER_ACE_MANAGE_DOCUMENTS
;
349 default: /* no change */
354 /* create a new SEC_DESC with the appropriate owner and group SIDs */
356 string_to_sid(&sid
, "S-1-5-32-544" );
357 new_sec
= make_sec_desc( ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
359 NULL
, NULL
, &size_new_sec
);
360 sd_new
= make_sec_desc_buf( ctx
, size_new_sec
, new_sec
);
362 if ( !(sd_store
= sec_desc_merge( ctx
, sd_new
, sd_orig
)) ) {
363 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key
.dptr
));
369 sd_size
= sec_desc_size(sd_store
->sec
) + sizeof(SEC_DESC_BUF
);
370 prs_init(&ps
, sd_size
, ctx
, MARSHALL
);
372 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store
, &ps
, 1 ) ) {
373 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key
.dptr
));
377 data
.dptr
= prs_data_p( &ps
);
378 data
.dsize
= sd_size
;
380 result
= tdb_store( tdb_printers
, key
, data
, TDB_REPLACE
);
384 /* 0 to continue and non-zero to stop traversal */
386 return (result
== -1);
389 /*******************************************************************
390 *******************************************************************/
392 static BOOL
upgrade_to_version_4(void)
397 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
399 if ( !(ctx
= talloc_init( "upgrade_to_version_4" )) )
402 result
= tdb_traverse( tdb_printers
, sec_desc_upg_fn
, ctx
);
404 talloc_destroy( ctx
);
406 return ( result
!= -1 );
409 /****************************************************************************
410 Open the NT printing tdbs. Done once before fork().
411 ****************************************************************************/
413 BOOL
nt_printing_init(void)
415 static pid_t local_pid
;
416 const char *vstring
= "INFO/version";
420 if (tdb_drivers
&& tdb_printers
&& tdb_forms
&& local_pid
== sys_getpid())
424 tdb_close(tdb_drivers
);
425 tdb_drivers
= tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
427 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
428 lock_path("ntdrivers.tdb"), strerror(errno
) ));
433 tdb_close(tdb_printers
);
434 tdb_printers
= tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
436 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
437 lock_path("ntprinters.tdb"), strerror(errno
) ));
442 tdb_close(tdb_forms
);
443 tdb_forms
= tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
445 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
446 lock_path("ntforms.tdb"), strerror(errno
) ));
450 local_pid
= sys_getpid();
452 /* handle a Samba upgrade */
453 tdb_lock_bystring(tdb_drivers
, vstring
, 0);
455 /* ---------------- Start Lock Region ---------------- */
457 /* Cope with byte-reversed older versions of the db. */
458 vers_id
= tdb_fetch_int32(tdb_drivers
, vstring
);
460 if ( vers_id
!= NTDRIVERS_DATABASE_VERSION
) {
462 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_2
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_2
)) {
463 /* Written on a bigendian machine with old fetch_int code. Save as le. */
464 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
465 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_3
);
466 vers_id
= NTDRIVERS_DATABASE_VERSION_3
;
469 if (vers_id
!= NTDRIVERS_DATABASE_VERSION_3
) {
471 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_1
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_1
)) {
472 if (!upgrade_to_version_3())
475 tdb_traverse(tdb_drivers
, tdb_traverse_delete_fn
, NULL
);
477 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_3
);
480 /* at this point we know that the database is at version 3 so upgrade to v4 */
482 if ( !upgrade_to_version_4() )
484 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION
);
487 /* ---------------- End Lock Region ------------------ */
489 tdb_unlock_bystring(tdb_drivers
, vstring
);
491 update_c_setprinter(True
);
494 * register callback to handle updating printers as new
495 * drivers are installed
498 message_register( MSG_PRINTER_DRVUPGRADE
, do_drv_upgrade_printer
);
501 * register callback to handle updating printer data
502 * when a driver is initialized
505 message_register( MSG_PRINTERDATA_INIT_RESET
, reset_all_printerdata
);
508 * register callback to handle invalidating the printer cache
509 * between smbd processes.
512 message_register( MSG_PRINTER_MOD
, receive_printer_mod_msg
);
514 /* of course, none of the message callbacks matter if you don't
515 tell messages.c that you interested in receiving PRINT_GENERAL
516 msgs. This is done in claim_connection() */
519 if ( lp_security() == SEC_ADS
) {
520 win_rc
= check_published_printers();
521 if (!W_ERROR_IS_OK(win_rc
))
522 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc
)));
528 /*******************************************************************
529 Function to allow filename parsing "the old way".
530 ********************************************************************/
532 static BOOL
driver_unix_convert(char *name
,connection_struct
*conn
,
533 char *saved_last_component
, BOOL
*bad_path
, SMB_STRUCT_STAT
*pst
)
536 unix_clean_name(name
);
537 trim_string(name
,"/","/");
538 return unix_convert(name
, conn
, saved_last_component
, bad_path
, pst
);
541 /*******************************************************************
542 tdb traversal function for counting printers.
543 ********************************************************************/
545 static int traverse_counting_printers(TDB_CONTEXT
*t
, TDB_DATA key
,
546 TDB_DATA data
, void *context
)
548 int *printer_count
= (int*)context
;
550 if (memcmp(PRINTERS_PREFIX
, key
.dptr
, sizeof(PRINTERS_PREFIX
)-1) == 0) {
552 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key
.dptr
, *printer_count
));
558 /*******************************************************************
559 Update the spooler global c_setprinter. This variable is initialized
560 when the parent smbd starts with the number of existing printers. It
561 is monotonically increased by the current number of printers *after*
562 each add or delete printer RPC. Only Microsoft knows why... JRR020119
563 ********************************************************************/
565 uint32
update_c_setprinter(BOOL initialize
)
568 int32 printer_count
= 0;
570 tdb_lock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
, 0);
572 /* Traverse the tdb, counting the printers */
573 tdb_traverse(tdb_printers
, traverse_counting_printers
, (void *)&printer_count
);
575 /* If initializing, set c_setprinter to current printers count
576 * otherwise, bump it by the current printer count
579 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
) + printer_count
;
581 c_setprinter
= printer_count
;
583 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter
));
584 tdb_store_int32(tdb_printers
, GLOBAL_C_SETPRINTER
, c_setprinter
);
586 tdb_unlock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
588 return (uint32
)c_setprinter
;
591 /*******************************************************************
592 Get the spooler global c_setprinter, accounting for initialization.
593 ********************************************************************/
595 uint32
get_c_setprinter(void)
597 int32 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
);
599 if (c_setprinter
== (int32
)-1)
600 c_setprinter
= update_c_setprinter(True
);
602 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter
));
604 return (uint32
)c_setprinter
;
607 /****************************************************************************
608 Get builtin form struct list.
609 ****************************************************************************/
611 int get_builtin_ntforms(nt_forms_struct
**list
)
613 *list
= (nt_forms_struct
*)memdup(&default_forms
[0], sizeof(default_forms
));
614 return sizeof(default_forms
) / sizeof(default_forms
[0]);
617 /****************************************************************************
618 get a builtin form struct
619 ****************************************************************************/
621 BOOL
get_a_builtin_ntform(UNISTR2
*uni_formname
,nt_forms_struct
*form
)
625 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
626 DEBUGADD(6,("Looking for builtin form %s \n", form_name
));
627 count
= sizeof(default_forms
) / sizeof(default_forms
[0]);
628 for (i
=0;i
<count
;i
++) {
629 if (strequal(form_name
,default_forms
[i
].name
)) {
630 DEBUGADD(6,("Found builtin form %s \n", form_name
));
631 memcpy(form
,&default_forms
[i
],sizeof(*form
));
639 /****************************************************************************
640 get a form struct list
641 ****************************************************************************/
642 int get_ntforms(nt_forms_struct
**list
)
644 TDB_DATA kbuf
, newkey
, dbuf
;
646 nt_forms_struct form
;
651 for (kbuf
= tdb_firstkey(tdb_forms
);
653 newkey
= tdb_nextkey(tdb_forms
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
)
655 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) != 0)
658 dbuf
= tdb_fetch(tdb_forms
, kbuf
);
662 fstrcpy(form
.name
, kbuf
.dptr
+strlen(FORMS_PREFIX
));
663 ret
= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dddddddd",
664 &i
, &form
.flag
, &form
.width
, &form
.length
, &form
.left
,
665 &form
.top
, &form
.right
, &form
.bottom
);
666 SAFE_FREE(dbuf
.dptr
);
667 if (ret
!= dbuf
.dsize
)
670 tl
= SMB_REALLOC_ARRAY(*list
, nt_forms_struct
, n
+1);
672 DEBUG(0,("get_ntforms: Realloc fail.\n"));
684 /****************************************************************************
685 write a form struct list
686 ****************************************************************************/
687 int write_ntforms(nt_forms_struct
**list
, int number
)
694 for (i
=0;i
<number
;i
++) {
695 /* save index, so list is rebuilt in correct order */
696 len
= tdb_pack(buf
, sizeof(buf
), "dddddddd",
697 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
698 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
700 if (len
> sizeof(buf
)) break;
701 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[i
].name
);
702 kbuf
.dsize
= strlen(key
)+1;
706 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) break;
712 /****************************************************************************
713 add a form struct at the end of the list
714 ****************************************************************************/
715 BOOL
add_a_form(nt_forms_struct
**list
, const FORM
*form
, int *count
)
723 * NT tries to add forms even when
724 * they are already in the base
725 * only update the values if already present
730 unistr2_to_ascii(form_name
, &form
->name
, sizeof(form_name
)-1);
731 for (n
=0; n
<*count
; n
++) {
732 if ( strequal((*list
)[n
].name
, form_name
) ) {
739 if((tl
=SMB_REALLOC_ARRAY(*list
, nt_forms_struct
, n
+1)) == NULL
) {
740 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
744 unistr2_to_ascii((*list
)[n
].name
, &form
->name
, sizeof((*list
)[n
].name
)-1);
748 (*list
)[n
].flag
=form
->flags
;
749 (*list
)[n
].width
=form
->size_x
;
750 (*list
)[n
].length
=form
->size_y
;
751 (*list
)[n
].left
=form
->left
;
752 (*list
)[n
].top
=form
->top
;
753 (*list
)[n
].right
=form
->right
;
754 (*list
)[n
].bottom
=form
->bottom
;
756 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
757 update
? "updated" : "added", form_name
));
762 /****************************************************************************
763 Delete a named form struct.
764 ****************************************************************************/
766 BOOL
delete_a_form(nt_forms_struct
**list
, UNISTR2
*del_name
, int *count
, WERROR
*ret
)
775 unistr2_to_ascii(form_name
, del_name
, sizeof(form_name
)-1);
777 for (n
=0; n
<*count
; n
++) {
778 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
779 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name
));
785 DEBUG(10,("delete_a_form, [%s] not found\n", form_name
));
786 *ret
= WERR_INVALID_PARAM
;
790 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[n
].name
);
791 kbuf
.dsize
= strlen(key
)+1;
793 if (tdb_delete(tdb_forms
, kbuf
) != 0) {
801 /****************************************************************************
802 Update a form struct.
803 ****************************************************************************/
805 void update_a_form(nt_forms_struct
**list
, const FORM
*form
, int count
)
809 unistr2_to_ascii(form_name
, &(form
->name
), sizeof(form_name
)-1);
811 DEBUG(106, ("[%s]\n", form_name
));
812 for (n
=0; n
<count
; n
++) {
813 DEBUGADD(106, ("n [%d]:[%s]\n", n
, (*list
)[n
].name
));
814 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
)))
818 if (n
==count
) return;
820 (*list
)[n
].flag
=form
->flags
;
821 (*list
)[n
].width
=form
->size_x
;
822 (*list
)[n
].length
=form
->size_y
;
823 (*list
)[n
].left
=form
->left
;
824 (*list
)[n
].top
=form
->top
;
825 (*list
)[n
].right
=form
->right
;
826 (*list
)[n
].bottom
=form
->bottom
;
829 /****************************************************************************
830 Get the nt drivers list.
831 Traverse the database and look-up the matching names.
832 ****************************************************************************/
833 int get_ntdrivers(fstring
**list
, const char *architecture
, uint32 version
)
836 const char *short_archi
;
839 TDB_DATA kbuf
, newkey
;
841 short_archi
= get_short_archi(architecture
);
842 slprintf(key
, sizeof(key
)-1, "%s%s/%d/", DRIVERS_PREFIX
, short_archi
, version
);
844 for (kbuf
= tdb_firstkey(tdb_drivers
);
846 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
848 if (strncmp(kbuf
.dptr
, key
, strlen(key
)) != 0)
851 if((fl
= SMB_REALLOC_ARRAY(*list
, fstring
, total
+1)) == NULL
) {
852 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
857 fstrcpy((*list
)[total
], kbuf
.dptr
+strlen(key
));
864 /****************************************************************************
865 function to do the mapping between the long architecture name and
867 ****************************************************************************/
868 const char *get_short_archi(const char *long_archi
)
872 DEBUG(107,("Getting architecture dependant directory\n"));
875 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
876 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
878 if (archi_table
[i
].long_archi
==NULL
) {
879 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
883 /* this might be client code - but shouldn't this be an fstrcpy etc? */
886 DEBUGADD(108,("index: [%d]\n", i
));
887 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
888 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
890 return archi_table
[i
].short_archi
;
893 /****************************************************************************
894 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
895 There are two case to be covered here: PE (Portable Executable) and NE (New
896 Executable) files. Both files support the same INFO structure, but PE files
897 store the signature in unicode, and NE files store it as !unicode.
898 returns -1 on error, 1 on version info found, and 0 on no version info found.
899 ****************************************************************************/
901 static int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
907 if ((buf
=SMB_MALLOC(PE_HEADER_SIZE
)) == NULL
) {
908 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
909 fname
, PE_HEADER_SIZE
));
913 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
914 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
915 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
916 fname
, (unsigned long)byte_count
));
917 goto no_version_info
;
920 /* Is this really a DOS header? */
921 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
922 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
923 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
924 goto no_version_info
;
927 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
928 if (SMB_VFS_LSEEK(fsp
, fsp
->fd
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
929 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
931 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
932 goto no_version_info
;
935 if ((byte_count
= vfs_read_data(fsp
, buf
, PE_HEADER_SIZE
)) < PE_HEADER_SIZE
) {
936 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
937 fname
, (unsigned long)byte_count
));
938 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
939 goto no_version_info
;
942 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
943 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
944 unsigned int num_sections
;
945 unsigned int section_table_bytes
;
947 if (SVAL(buf
,PE_HEADER_MACHINE_OFFSET
) != PE_HEADER_MACHINE_I386
) {
948 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
949 fname
, SVAL(buf
,PE_HEADER_MACHINE_OFFSET
)));
950 /* At this point, we assume the file is in error. It still could be somthing
951 * else besides a PE file, but it unlikely at this point.
956 /* get the section table */
957 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
958 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
959 if (section_table_bytes
== 0)
963 if ((buf
=SMB_MALLOC(section_table_bytes
)) == NULL
) {
964 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
965 fname
, section_table_bytes
));
969 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
970 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
971 fname
, (unsigned long)byte_count
));
975 /* Iterate the section table looking for the resource section ".rsrc" */
976 for (i
= 0; i
< num_sections
; i
++) {
977 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
979 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
980 unsigned int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
981 unsigned int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
983 if (section_bytes
== 0)
987 if ((buf
=SMB_MALLOC(section_bytes
)) == NULL
) {
988 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
989 fname
, section_bytes
));
993 /* Seek to the start of the .rsrc section info */
994 if (SMB_VFS_LSEEK(fsp
, fsp
->fd
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
995 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1000 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
1001 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1002 fname
, (unsigned long)byte_count
));
1006 if (section_bytes
< VS_VERSION_INFO_UNICODE_SIZE
)
1009 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
1010 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1011 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
1012 /* Align to next long address */
1013 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
1015 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
1016 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
1017 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
1019 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1020 fname
, *major
, *minor
,
1021 (*major
>>16)&0xffff, *major
&0xffff,
1022 (*minor
>>16)&0xffff, *minor
&0xffff));
1031 /* Version info not found, fall back to origin date/time */
1032 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
1036 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
1037 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
1038 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1039 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
1040 /* At this point, we assume the file is in error. It still could be somthing
1041 * else besides a NE file, but it unlikely at this point. */
1045 /* Allocate a bit more space to speed up things */
1047 if ((buf
=SMB_MALLOC(VS_NE_BUF_SIZE
)) == NULL
) {
1048 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1049 fname
, PE_HEADER_SIZE
));
1053 /* This is a HACK! I got tired of trying to sort through the messy
1054 * 'NE' file format. If anyone wants to clean this up please have at
1055 * it, but this works. 'NE' files will eventually fade away. JRR */
1056 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
1057 /* Cover case that should not occur in a well formed 'NE' .dll file */
1058 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
1060 for(i
=0; i
<byte_count
; i
++) {
1061 /* Fast skip past data that can't possibly match */
1062 if (buf
[i
] != 'V') continue;
1064 /* Potential match data crosses buf boundry, move it to beginning
1065 * of buf, and fill the buf with as much as it will hold. */
1066 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
1069 memcpy(buf
, &buf
[i
], byte_count
-i
);
1070 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
1071 (byte_count
-i
))) < 0) {
1073 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1078 byte_count
= bc
+ (byte_count
- i
);
1079 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
1084 /* Check that the full signature string and the magic number that
1085 * follows exist (not a perfect solution, but the chances that this
1086 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1087 * twice, as it is simpler to read the code. */
1088 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
1089 /* Compute skip alignment to next long address */
1090 int skip
= -(SMB_VFS_LSEEK(fsp
, fsp
->fd
, 0, SEEK_CUR
) - (byte_count
- i
) +
1091 sizeof(VS_SIGNATURE
)) & 3;
1092 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
1094 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
1095 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
1096 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1097 fname
, *major
, *minor
,
1098 (*major
>>16)&0xffff, *major
&0xffff,
1099 (*minor
>>16)&0xffff, *minor
&0xffff));
1106 /* Version info not found, fall back to origin date/time */
1107 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
1112 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1113 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1114 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
1125 /****************************************************************************
1126 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1127 share one or more files. During the MS installation process files are checked
1128 to insure that only a newer version of a shared file is installed over an
1129 older version. There are several possibilities for this comparison. If there
1130 is no previous version, the new one is newer (obviously). If either file is
1131 missing the version info structure, compare the creation date (on Unix use
1132 the modification date). Otherwise chose the numerically larger version number.
1133 ****************************************************************************/
1135 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
1137 BOOL use_version
= True
;
1142 time_t new_create_time
;
1146 time_t old_create_time
;
1150 files_struct
*fsp
= NULL
;
1152 SMB_STRUCT_STAT stat_buf
;
1155 SET_STAT_INVALID(st
);
1156 SET_STAT_INVALID(stat_buf
);
1157 new_create_time
= (time_t)0;
1158 old_create_time
= (time_t)0;
1160 /* Get file version info (if available) for previous file (if it exists) */
1161 pstrcpy(filepath
, old_file
);
1163 driver_unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1165 fsp
= open_file_shared(conn
, filepath
, &stat_buf
,
1166 SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
1167 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1168 FILE_ATTRIBUTE_NORMAL
, INTERNAL_OPEN_ONLY
, &access_mode
, &action
);
1170 /* Old file not found, so by definition new file is in fact newer */
1171 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1176 int ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
1177 if (ret
== -1) goto error_exit
;
1180 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1182 use_version
= False
;
1183 if (SMB_VFS_FSTAT(fsp
, fsp
->fd
, &st
) == -1) goto error_exit
;
1184 old_create_time
= st
.st_mtime
;
1185 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time
));
1188 close_file(fsp
, True
);
1190 /* Get file version info (if available) for new file */
1191 pstrcpy(filepath
, new_file
);
1192 driver_unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1194 fsp
= open_file_shared(conn
, filepath
, &stat_buf
,
1195 SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
1196 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1197 FILE_ATTRIBUTE_NORMAL
, INTERNAL_OPEN_ONLY
, &access_mode
, &action
);
1199 /* New file not found, this shouldn't occur if the caller did its job */
1200 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1205 int ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
1206 if (ret
== -1) goto error_exit
;
1209 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1211 use_version
= False
;
1212 if (SMB_VFS_FSTAT(fsp
, fsp
->fd
, &st
) == -1) goto error_exit
;
1213 new_create_time
= st
.st_mtime
;
1214 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time
));
1217 close_file(fsp
, True
);
1219 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
1220 /* Compare versions and choose the larger version number */
1221 if (new_major
> old_major
||
1222 (new_major
== old_major
&& new_minor
> old_minor
)) {
1224 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1228 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1233 /* Compare modification time/dates and choose the newest time/date */
1234 if (new_create_time
> old_create_time
) {
1235 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1239 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1246 close_file(fsp
, True
);
1250 /****************************************************************************
1251 Determine the correct cVersion associated with an architecture and driver
1252 ****************************************************************************/
1253 static uint32
get_correct_cversion(const char *architecture
, fstring driverpath_in
,
1254 struct current_user
*user
, WERROR
*perr
)
1263 files_struct
*fsp
= NULL
;
1266 connection_struct
*conn
;
1268 SET_STAT_INVALID(st
);
1270 *perr
= WERR_INVALID_PARAM
;
1272 /* If architecture is Windows 95/98/ME, the version is always 0. */
1273 if (strcmp(architecture
, "WIN40") == 0) {
1274 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1280 * Connect to the print$ share under the same account as the user connected
1281 * to the rpc pipe. Note we must still be root to do this.
1284 /* Null password is ok - we are already an authenticated user... */
1285 null_pw
= data_blob(NULL
, 0);
1286 fstrcpy(res_type
, "A:");
1288 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1292 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1293 *perr
= ntstatus_to_werror(nt_status
);
1297 /* We are temporarily becoming the connection user. */
1298 if (!become_user(conn
, user
->vuid
)) {
1299 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1300 *perr
= WERR_ACCESS_DENIED
;
1304 /* Open the driver file (Portable Executable format) and determine the
1305 * deriver the cversion. */
1306 slprintf(driverpath
, sizeof(driverpath
)-1, "%s/%s", architecture
, driverpath_in
);
1308 driver_unix_convert(driverpath
,conn
,NULL
,&bad_path
,&st
);
1310 if ( !vfs_file_exist( conn
, driverpath
, &st
) ) {
1311 *perr
= WERR_BADFILE
;
1315 fsp
= open_file_shared(conn
, driverpath
, &st
,
1316 SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
1317 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
1318 FILE_ATTRIBUTE_NORMAL
, INTERNAL_OPEN_ONLY
, &access_mode
, &action
);
1321 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1322 driverpath
, errno
));
1323 *perr
= WERR_ACCESS_DENIED
;
1329 int ret
= get_file_version(fsp
, driverpath
, &major
, &minor
);
1330 if (ret
== -1) goto error_exit
;
1333 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath
));
1338 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1339 * for more details. Version in this case is not just the version of the
1340 * file, but the version in the sense of kernal mode (2) vs. user mode
1341 * (3) drivers. Other bits of the version fields are the version info.
1344 cversion
= major
& 0x0000ffff;
1346 case 2: /* WinNT drivers */
1347 case 3: /* Win2K drivers */
1351 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1352 driverpath
, cversion
));
1356 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1357 driverpath
, major
, minor
));
1360 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1361 driverpath
, cversion
));
1363 close_file(fsp
, True
);
1364 close_cnum(conn
, user
->vuid
);
1373 close_file(fsp
, True
);
1375 close_cnum(conn
, user
->vuid
);
1380 /****************************************************************************
1381 ****************************************************************************/
1382 static WERROR
clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
,
1383 struct current_user
*user
)
1385 const char *architecture
;
1391 /* clean up the driver name.
1392 * we can get .\driver.dll
1393 * or worse c:\windows\system\driver.dll !
1395 /* using an intermediate string to not have overlaping memcpy()'s */
1396 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1397 fstrcpy(new_name
, p
+1);
1398 fstrcpy(driver
->driverpath
, new_name
);
1401 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1402 fstrcpy(new_name
, p
+1);
1403 fstrcpy(driver
->datafile
, new_name
);
1406 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1407 fstrcpy(new_name
, p
+1);
1408 fstrcpy(driver
->configfile
, new_name
);
1411 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1412 fstrcpy(new_name
, p
+1);
1413 fstrcpy(driver
->helpfile
, new_name
);
1416 if (driver
->dependentfiles
) {
1417 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1418 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1419 fstrcpy(new_name
, p
+1);
1420 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1425 architecture
= get_short_archi(driver
->environment
);
1427 /* jfm:7/16/2000 the client always sends the cversion=0.
1428 * The server should check which version the driver is by reading
1429 * the PE header of driver->driverpath.
1431 * For Windows 95/98 the version is 0 (so the value sent is correct)
1432 * For Windows NT (the architecture doesn't matter)
1433 * NT 3.1: cversion=0
1434 * NT 3.5/3.51: cversion=1
1438 if ((driver
->cversion
= get_correct_cversion( architecture
, driver
->driverpath
, user
, &err
)) == -1)
1444 /****************************************************************************
1445 ****************************************************************************/
1446 static WERROR
clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
, struct current_user
*user
)
1448 const char *architecture
;
1454 /* clean up the driver name.
1455 * we can get .\driver.dll
1456 * or worse c:\windows\system\driver.dll !
1458 /* using an intermediate string to not have overlaping memcpy()'s */
1459 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1460 fstrcpy(new_name
, p
+1);
1461 fstrcpy(driver
->driverpath
, new_name
);
1464 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1465 fstrcpy(new_name
, p
+1);
1466 fstrcpy(driver
->datafile
, new_name
);
1469 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1470 fstrcpy(new_name
, p
+1);
1471 fstrcpy(driver
->configfile
, new_name
);
1474 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1475 fstrcpy(new_name
, p
+1);
1476 fstrcpy(driver
->helpfile
, new_name
);
1479 if (driver
->dependentfiles
) {
1480 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1481 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1482 fstrcpy(new_name
, p
+1);
1483 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1488 architecture
= get_short_archi(driver
->environment
);
1490 /* jfm:7/16/2000 the client always sends the cversion=0.
1491 * The server should check which version the driver is by reading
1492 * the PE header of driver->driverpath.
1494 * For Windows 95/98 the version is 0 (so the value sent is correct)
1495 * For Windows NT (the architecture doesn't matter)
1496 * NT 3.1: cversion=0
1497 * NT 3.5/3.51: cversion=1
1502 if ((driver
->version
= get_correct_cversion(architecture
, driver
->driverpath
, user
, &err
)) == -1)
1508 /****************************************************************************
1509 ****************************************************************************/
1510 WERROR
clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
,
1511 uint32 level
, struct current_user
*user
)
1516 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1517 driver
=driver_abstract
.info_3
;
1518 return clean_up_driver_struct_level_3(driver
, user
);
1522 NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
;
1523 driver
=driver_abstract
.info_6
;
1524 return clean_up_driver_struct_level_6(driver
, user
);
1527 return WERR_INVALID_PARAM
;
1531 /****************************************************************************
1532 This function sucks and should be replaced. JRA.
1533 ****************************************************************************/
1535 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*dst
, NT_PRINTER_DRIVER_INFO_LEVEL_6
*src
)
1537 dst
->cversion
= src
->version
;
1539 fstrcpy( dst
->name
, src
->name
);
1540 fstrcpy( dst
->environment
, src
->environment
);
1541 fstrcpy( dst
->driverpath
, src
->driverpath
);
1542 fstrcpy( dst
->datafile
, src
->datafile
);
1543 fstrcpy( dst
->configfile
, src
->configfile
);
1544 fstrcpy( dst
->helpfile
, src
->helpfile
);
1545 fstrcpy( dst
->monitorname
, src
->monitorname
);
1546 fstrcpy( dst
->defaultdatatype
, src
->defaultdatatype
);
1547 dst
->dependentfiles
= src
->dependentfiles
;
1550 #if 0 /* Debugging function */
1552 static char* ffmt(unsigned char *c
){
1554 static char ffmt_str
[17];
1556 for (i
=0; i
<16; i
++) {
1557 if ((c
[i
] < ' ') || (c
[i
] > '~'))
1568 /****************************************************************************
1569 ****************************************************************************/
1570 WERROR
move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
, uint32 level
,
1571 struct current_user
*user
, WERROR
*perr
)
1573 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1574 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver
;
1575 const char *architecture
;
1580 connection_struct
*conn
;
1591 memset(inbuf
, '\0', sizeof(inbuf
));
1592 memset(outbuf
, '\0', sizeof(outbuf
));
1596 driver
=driver_abstract
.info_3
;
1597 else if (level
==6) {
1598 convert_level_6_to_level3(&converted_driver
, driver_abstract
.info_6
);
1599 driver
= &converted_driver
;
1601 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level
));
1602 return WERR_UNKNOWN_LEVEL
;
1605 architecture
= get_short_archi(driver
->environment
);
1608 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1609 * Note we must be root to do this.
1612 null_pw
= data_blob(NULL
, 0);
1613 fstrcpy(res_type
, "A:");
1615 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1619 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1620 *perr
= ntstatus_to_werror(nt_status
);
1621 return WERR_NO_SUCH_SHARE
;
1625 * Save who we are - we are temporarily becoming the connection user.
1628 if (!become_user(conn
, conn
->vuid
)) {
1629 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1630 return WERR_ACCESS_DENIED
;
1634 * make the directories version and version\driver_name
1635 * under the architecture directory.
1637 DEBUG(5,("Creating first directory\n"));
1638 slprintf(new_dir
, sizeof(new_dir
)-1, "%s/%d", architecture
, driver
->cversion
);
1639 driver_unix_convert(new_dir
, conn
, NULL
, &bad_path
, &st
);
1640 mkdir_internal(conn
, new_dir
, bad_path
);
1642 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1643 * listed for this driver which has already been moved, skip it (note:
1644 * drivers may list the same file name several times. Then check if the
1645 * file already exists in archi\cversion\, if so, check that the version
1646 * info (or time stamps if version info is unavailable) is newer (or the
1647 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1648 * Otherwise, delete the file.
1650 * If a file is not moved to archi\cversion\ because of an error, all the
1651 * rest of the 'unmoved' driver files are removed from archi\. If one or
1652 * more of the driver's files was already moved to archi\cversion\, it
1653 * potentially leaves the driver in a partially updated state. Version
1654 * trauma will most likely occur if an client attempts to use any printer
1655 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1656 * done is appropriate... later JRR
1659 DEBUG(5,("Moving files now !\n"));
1661 if (driver
->driverpath
&& strlen(driver
->driverpath
)) {
1662 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->driverpath
);
1663 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->driverpath
);
1664 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1666 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1667 if ( !copy_file(new_name
, old_name
, conn
, FILE_EXISTS_TRUNCATE
|FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1668 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1669 new_name
, old_name
));
1670 *perr
= ntstatus_to_werror(status
);
1676 if (driver
->datafile
&& strlen(driver
->datafile
)) {
1677 if (!strequal(driver
->datafile
, driver
->driverpath
)) {
1678 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->datafile
);
1679 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->datafile
);
1680 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1682 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1683 if ( !copy_file(new_name
, old_name
, conn
, FILE_EXISTS_TRUNCATE
|FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1684 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1685 new_name
, old_name
));
1686 *perr
= ntstatus_to_werror(status
);
1693 if (driver
->configfile
&& strlen(driver
->configfile
)) {
1694 if (!strequal(driver
->configfile
, driver
->driverpath
) &&
1695 !strequal(driver
->configfile
, driver
->datafile
)) {
1696 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->configfile
);
1697 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->configfile
);
1698 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1700 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1701 if ( !copy_file(new_name
, old_name
, conn
, FILE_EXISTS_TRUNCATE
|FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1702 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1703 new_name
, old_name
));
1704 *perr
= ntstatus_to_werror(status
);
1711 if (driver
->helpfile
&& strlen(driver
->helpfile
)) {
1712 if (!strequal(driver
->helpfile
, driver
->driverpath
) &&
1713 !strequal(driver
->helpfile
, driver
->datafile
) &&
1714 !strequal(driver
->helpfile
, driver
->configfile
)) {
1715 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->helpfile
);
1716 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->helpfile
);
1717 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1719 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1720 if ( !copy_file(new_name
, old_name
, conn
, FILE_EXISTS_TRUNCATE
|FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1721 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1722 new_name
, old_name
));
1723 *perr
= ntstatus_to_werror(status
);
1730 if (driver
->dependentfiles
) {
1731 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1732 if (!strequal(driver
->dependentfiles
[i
], driver
->driverpath
) &&
1733 !strequal(driver
->dependentfiles
[i
], driver
->datafile
) &&
1734 !strequal(driver
->dependentfiles
[i
], driver
->configfile
) &&
1735 !strequal(driver
->dependentfiles
[i
], driver
->helpfile
)) {
1737 for (j
=0; j
< i
; j
++) {
1738 if (strequal(driver
->dependentfiles
[i
], driver
->dependentfiles
[j
])) {
1743 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->dependentfiles
[i
]);
1744 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->dependentfiles
[i
]);
1745 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1747 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1748 if ( !copy_file(new_name
, old_name
, conn
, FILE_EXISTS_TRUNCATE
|FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1749 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1750 new_name
, old_name
));
1751 *perr
= ntstatus_to_werror(status
);
1760 close_cnum(conn
, user
->vuid
);
1763 return ver
!= -1 ? WERR_OK
: WERR_UNKNOWN_PRINTER_DRIVER
;
1766 /****************************************************************************
1767 ****************************************************************************/
1768 static uint32
add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
)
1771 const char *architecture
;
1777 TDB_DATA kbuf
, dbuf
;
1779 architecture
= get_short_archi(driver
->environment
);
1781 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1782 * \\server is added in the rpc server layer.
1783 * It does make sense to NOT store the server's name in the printer TDB.
1786 slprintf(directory
, sizeof(directory
)-1, "\\print$\\%s\\%d\\", architecture
, driver
->cversion
);
1788 /* .inf files do not always list a file for each of the four standard files.
1789 * Don't prepend a path to a null filename, or client claims:
1790 * "The server on which the printer resides does not have a suitable
1791 * <printer driver name> printer driver installed. Click OK if you
1792 * wish to install the driver on your local machine."
1794 if (strlen(driver
->driverpath
)) {
1795 fstrcpy(temp_name
, driver
->driverpath
);
1796 slprintf(driver
->driverpath
, sizeof(driver
->driverpath
)-1, "%s%s", directory
, temp_name
);
1799 if (strlen(driver
->datafile
)) {
1800 fstrcpy(temp_name
, driver
->datafile
);
1801 slprintf(driver
->datafile
, sizeof(driver
->datafile
)-1, "%s%s", directory
, temp_name
);
1804 if (strlen(driver
->configfile
)) {
1805 fstrcpy(temp_name
, driver
->configfile
);
1806 slprintf(driver
->configfile
, sizeof(driver
->configfile
)-1, "%s%s", directory
, temp_name
);
1809 if (strlen(driver
->helpfile
)) {
1810 fstrcpy(temp_name
, driver
->helpfile
);
1811 slprintf(driver
->helpfile
, sizeof(driver
->helpfile
)-1, "%s%s", directory
, temp_name
);
1814 if (driver
->dependentfiles
) {
1815 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1816 fstrcpy(temp_name
, driver
->dependentfiles
[i
]);
1817 slprintf(driver
->dependentfiles
[i
], sizeof(driver
->dependentfiles
[i
])-1, "%s%s", directory
, temp_name
);
1821 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, driver
->cversion
, driver
->name
);
1823 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key
));
1830 len
+= tdb_pack(buf
+len
, buflen
-len
, "dffffffff",
1833 driver
->environment
,
1838 driver
->monitorname
,
1839 driver
->defaultdatatype
);
1841 if (driver
->dependentfiles
) {
1842 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1843 len
+= tdb_pack(buf
+len
, buflen
-len
, "f",
1844 driver
->dependentfiles
[i
]);
1848 if (len
!= buflen
) {
1851 tb
= (char *)SMB_REALLOC(buf
, len
);
1853 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1864 kbuf
.dsize
= strlen(key
)+1;
1868 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
1872 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key
));
1878 /****************************************************************************
1879 ****************************************************************************/
1880 static uint32
add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
)
1882 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3
;
1885 info3
.cversion
= driver
->version
;
1886 fstrcpy(info3
.name
,driver
->name
);
1887 fstrcpy(info3
.environment
,driver
->environment
);
1888 fstrcpy(info3
.driverpath
,driver
->driverpath
);
1889 fstrcpy(info3
.datafile
,driver
->datafile
);
1890 fstrcpy(info3
.configfile
,driver
->configfile
);
1891 fstrcpy(info3
.helpfile
,driver
->helpfile
);
1892 fstrcpy(info3
.monitorname
,driver
->monitorname
);
1893 fstrcpy(info3
.defaultdatatype
,driver
->defaultdatatype
);
1894 info3
.dependentfiles
= driver
->dependentfiles
;
1896 return add_a_printer_driver_3(&info3
);
1900 /****************************************************************************
1901 ****************************************************************************/
1902 static WERROR
get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, const char *driver
, const char *arch
)
1904 NT_PRINTER_DRIVER_INFO_LEVEL_3 info
;
1908 fstrcpy(info
.name
, driver
);
1909 fstrcpy(info
.defaultdatatype
, "RAW");
1911 fstrcpy(info
.driverpath
, "");
1912 fstrcpy(info
.datafile
, "");
1913 fstrcpy(info
.configfile
, "");
1914 fstrcpy(info
.helpfile
, "");
1916 if ((info
.dependentfiles
= SMB_MALLOC_ARRAY(fstring
, 2)) == NULL
)
1919 memset(info
.dependentfiles
, '\0', 2*sizeof(fstring
));
1920 fstrcpy(info
.dependentfiles
[0], "");
1922 *info_ptr
= memdup(&info
, sizeof(info
));
1927 /****************************************************************************
1928 ****************************************************************************/
1929 static WERROR
get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, fstring drivername
, const char *arch
, uint32 version
)
1931 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver
;
1932 TDB_DATA kbuf
, dbuf
;
1933 const char *architecture
;
1938 ZERO_STRUCT(driver
);
1940 architecture
= get_short_archi(arch
);
1942 if ( !architecture
)
1943 return WERR_UNKNOWN_PRINTER_DRIVER
;
1945 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1947 if ( strcmp( architecture
, SPL_ARCH_WIN40
) == 0 )
1950 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX
, architecture
, version
, drivername
));
1952 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, version
, drivername
);
1955 kbuf
.dsize
= strlen(key
)+1;
1957 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
1959 return WERR_UNKNOWN_PRINTER_DRIVER
;
1961 len
+= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dffffffff",
1970 driver
.defaultdatatype
);
1973 while (len
< dbuf
.dsize
) {
1976 tddfs
= SMB_REALLOC_ARRAY(driver
.dependentfiles
, fstring
, i
+2);
1977 if (tddfs
== NULL
) {
1978 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1981 else driver
.dependentfiles
= tddfs
;
1983 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "f",
1984 &driver
.dependentfiles
[i
]);
1988 if (driver
.dependentfiles
!= NULL
)
1989 fstrcpy(driver
.dependentfiles
[i
], "");
1991 SAFE_FREE(dbuf
.dptr
);
1993 if (len
!= dbuf
.dsize
) {
1994 SAFE_FREE(driver
.dependentfiles
);
1996 return get_a_printer_driver_3_default(info_ptr
, drivername
, arch
);
1999 *info_ptr
= (NT_PRINTER_DRIVER_INFO_LEVEL_3
*)memdup(&driver
, sizeof(driver
));
2004 /****************************************************************************
2005 Debugging function, dump at level 6 the struct in the logs.
2006 ****************************************************************************/
2008 static uint32
dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
2011 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
2014 DEBUG(20,("Dumping printer driver at level [%d]\n", level
));
2020 if (driver
.info_3
== NULL
)
2023 info3
=driver
.info_3
;
2025 DEBUGADD(20,("version:[%d]\n", info3
->cversion
));
2026 DEBUGADD(20,("name:[%s]\n", info3
->name
));
2027 DEBUGADD(20,("environment:[%s]\n", info3
->environment
));
2028 DEBUGADD(20,("driverpath:[%s]\n", info3
->driverpath
));
2029 DEBUGADD(20,("datafile:[%s]\n", info3
->datafile
));
2030 DEBUGADD(20,("configfile:[%s]\n", info3
->configfile
));
2031 DEBUGADD(20,("helpfile:[%s]\n", info3
->helpfile
));
2032 DEBUGADD(20,("monitorname:[%s]\n", info3
->monitorname
));
2033 DEBUGADD(20,("defaultdatatype:[%s]\n", info3
->defaultdatatype
));
2035 for (i
=0; info3
->dependentfiles
&&
2036 *info3
->dependentfiles
[i
]; i
++) {
2037 DEBUGADD(20,("dependentfile:[%s]\n",
2038 info3
->dependentfiles
[i
]));
2045 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level
));
2053 /****************************************************************************
2054 ****************************************************************************/
2055 int pack_devicemode(NT_DEVICEMODE
*nt_devmode
, char *buf
, int buflen
)
2059 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2064 len
+= tdb_pack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2065 nt_devmode
->devicename
,
2066 nt_devmode
->formname
,
2068 nt_devmode
->specversion
,
2069 nt_devmode
->driverversion
,
2071 nt_devmode
->driverextra
,
2072 nt_devmode
->orientation
,
2073 nt_devmode
->papersize
,
2074 nt_devmode
->paperlength
,
2075 nt_devmode
->paperwidth
,
2078 nt_devmode
->defaultsource
,
2079 nt_devmode
->printquality
,
2082 nt_devmode
->yresolution
,
2083 nt_devmode
->ttoption
,
2084 nt_devmode
->collate
,
2085 nt_devmode
->logpixels
,
2088 nt_devmode
->bitsperpel
,
2089 nt_devmode
->pelswidth
,
2090 nt_devmode
->pelsheight
,
2091 nt_devmode
->displayflags
,
2092 nt_devmode
->displayfrequency
,
2093 nt_devmode
->icmmethod
,
2094 nt_devmode
->icmintent
,
2095 nt_devmode
->mediatype
,
2096 nt_devmode
->dithertype
,
2097 nt_devmode
->reserved1
,
2098 nt_devmode
->reserved2
,
2099 nt_devmode
->panningwidth
,
2100 nt_devmode
->panningheight
,
2101 nt_devmode
->private);
2104 if (nt_devmode
->private) {
2105 len
+= tdb_pack(buf
+len
, buflen
-len
, "B",
2106 nt_devmode
->driverextra
,
2107 nt_devmode
->private);
2110 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode
->formname
));
2115 /****************************************************************************
2116 Pack all values in all printer keys
2117 ***************************************************************************/
2119 static int pack_values(NT_PRINTER_DATA
*data
, char *buf
, int buflen
)
2123 REGISTRY_VALUE
*val
;
2124 REGVAL_CTR
*val_ctr
;
2131 /* loop over all keys */
2133 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2134 val_ctr
= &data
->keys
[i
].values
;
2135 num_values
= regval_ctr_numvals( val_ctr
);
2137 /* loop over all values */
2139 for ( j
=0; j
<num_values
; j
++ ) {
2140 /* pathname should be stored as <key>\<value> */
2142 val
= regval_ctr_specific_value( val_ctr
, j
);
2143 pstrcpy( path
, data
->keys
[i
].name
);
2144 pstrcat( path
, "\\" );
2145 pstrcat( path
, regval_name(val
) );
2147 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2152 regval_data_p(val
) );
2159 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", NULL
);
2165 /****************************************************************************
2166 Delete a printer - this just deletes the printer info file, any open
2167 handles are not affected.
2168 ****************************************************************************/
2170 uint32
del_a_printer(const char *sharename
)
2174 pstring printdb_path
;
2176 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
2178 kbuf
.dsize
=strlen(key
)+1;
2179 tdb_delete(tdb_printers
, kbuf
);
2181 slprintf(key
, sizeof(key
)-1, "%s%s", SECDESC_PREFIX
, sharename
);
2183 kbuf
.dsize
=strlen(key
)+1;
2184 tdb_delete(tdb_printers
, kbuf
);
2186 close_all_print_db();
2188 if (geteuid() == 0) {
2189 pstrcpy(printdb_path
, lock_path("printing/"));
2190 pstrcat(printdb_path
, sharename
);
2191 pstrcat(printdb_path
, ".tdb");
2193 unlink(printdb_path
);
2199 /****************************************************************************
2200 ****************************************************************************/
2201 static WERROR
update_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
)
2207 TDB_DATA kbuf
, dbuf
;
2210 * in addprinter: no servername and the printer is the name
2211 * in setprinter: servername is \\server
2212 * and printer is \\server\\printer
2214 * Samba manages only local printers.
2215 * we currently don't support things like i
2216 * path=\\other_server\printer
2218 * We only store the printername, not \\server\printername
2221 if ( info
->servername
[0] != '\0' ) {
2222 trim_string(info
->printername
, info
->servername
, NULL
);
2223 trim_char(info
->printername
, '\\', '\0');
2224 info
->servername
[0]='\0';
2228 * JFM: one day I'll forget.
2229 * below that's info->portname because that's the SAMBA sharename
2230 * and I made NT 'thinks' it's the portname
2231 * the info->sharename is the thing you can name when you add a printer
2232 * that's the short-name when you create shared printer for 95/98
2233 * So I've made a limitation in SAMBA: you can only have 1 printer model
2234 * behind a SAMBA share.
2242 len
+= tdb_pack(buf
+len
, buflen
-len
, "dddddddddddfffffPfffff",
2245 info
->default_priority
,
2262 info
->printprocessor
,
2266 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
2268 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
2270 if (buflen
!= len
) {
2273 tb
= (char *)SMB_REALLOC(buf
, len
);
2275 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2285 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, info
->sharename
);
2288 kbuf
.dsize
= strlen(key
)+1;
2292 ret
= (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) == 0? WERR_OK
: WERR_NOMEM
);
2295 if (!W_ERROR_IS_OK(ret
))
2296 DEBUG(8, ("error updating printer to tdb on disk\n"));
2300 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2301 info
->sharename
, info
->drivername
, info
->portname
, len
));
2307 /****************************************************************************
2308 Malloc and return an NT devicemode.
2309 ****************************************************************************/
2311 NT_DEVICEMODE
*construct_nt_devicemode(const fstring default_devicename
)
2314 char adevice
[MAXDEVICENAME
];
2315 NT_DEVICEMODE
*nt_devmode
= SMB_MALLOC_P(NT_DEVICEMODE
);
2317 if (nt_devmode
== NULL
) {
2318 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2322 ZERO_STRUCTP(nt_devmode
);
2324 slprintf(adevice
, sizeof(adevice
), "%s", default_devicename
);
2325 fstrcpy(nt_devmode
->devicename
, adevice
);
2327 fstrcpy(nt_devmode
->formname
, "Letter");
2329 nt_devmode
->specversion
= 0x0401;
2330 nt_devmode
->driverversion
= 0x0400;
2331 nt_devmode
->size
= 0x00DC;
2332 nt_devmode
->driverextra
= 0x0000;
2333 nt_devmode
->fields
= FORMNAME
| TTOPTION
| PRINTQUALITY
|
2334 DEFAULTSOURCE
| COPIES
| SCALE
|
2335 PAPERSIZE
| ORIENTATION
;
2336 nt_devmode
->orientation
= 1;
2337 nt_devmode
->papersize
= PAPER_LETTER
;
2338 nt_devmode
->paperlength
= 0;
2339 nt_devmode
->paperwidth
= 0;
2340 nt_devmode
->scale
= 0x64;
2341 nt_devmode
->copies
= 1;
2342 nt_devmode
->defaultsource
= BIN_FORMSOURCE
;
2343 nt_devmode
->printquality
= RES_HIGH
; /* 0x0258 */
2344 nt_devmode
->color
= COLOR_MONOCHROME
;
2345 nt_devmode
->duplex
= DUP_SIMPLEX
;
2346 nt_devmode
->yresolution
= 0;
2347 nt_devmode
->ttoption
= TT_SUBDEV
;
2348 nt_devmode
->collate
= COLLATE_FALSE
;
2349 nt_devmode
->icmmethod
= 0;
2350 nt_devmode
->icmintent
= 0;
2351 nt_devmode
->mediatype
= 0;
2352 nt_devmode
->dithertype
= 0;
2354 /* non utilisés par un driver d'imprimante */
2355 nt_devmode
->logpixels
= 0;
2356 nt_devmode
->bitsperpel
= 0;
2357 nt_devmode
->pelswidth
= 0;
2358 nt_devmode
->pelsheight
= 0;
2359 nt_devmode
->displayflags
= 0;
2360 nt_devmode
->displayfrequency
= 0;
2361 nt_devmode
->reserved1
= 0;
2362 nt_devmode
->reserved2
= 0;
2363 nt_devmode
->panningwidth
= 0;
2364 nt_devmode
->panningheight
= 0;
2366 nt_devmode
->private = NULL
;
2370 /****************************************************************************
2371 Deepcopy an NT devicemode.
2372 ****************************************************************************/
2374 NT_DEVICEMODE
*dup_nt_devicemode(NT_DEVICEMODE
*nt_devicemode
)
2376 NT_DEVICEMODE
*new_nt_devicemode
= NULL
;
2378 if ( !nt_devicemode
)
2381 if ((new_nt_devicemode
= (NT_DEVICEMODE
*)memdup(nt_devicemode
, sizeof(NT_DEVICEMODE
))) == NULL
) {
2382 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2386 new_nt_devicemode
->private = NULL
;
2387 if (nt_devicemode
->private != NULL
) {
2388 if ((new_nt_devicemode
->private = memdup(nt_devicemode
->private, nt_devicemode
->driverextra
)) == NULL
) {
2389 SAFE_FREE(new_nt_devicemode
);
2390 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2395 return new_nt_devicemode
;
2398 /****************************************************************************
2399 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2400 ****************************************************************************/
2402 void free_nt_devicemode(NT_DEVICEMODE
**devmode_ptr
)
2404 NT_DEVICEMODE
*nt_devmode
= *devmode_ptr
;
2406 if(nt_devmode
== NULL
)
2409 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2411 SAFE_FREE(nt_devmode
->private);
2412 SAFE_FREE(*devmode_ptr
);
2415 /****************************************************************************
2416 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2417 ****************************************************************************/
2418 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
)
2420 NT_PRINTER_INFO_LEVEL_2
*info
= *info_ptr
;
2421 NT_PRINTER_DATA
*data
;
2427 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2429 free_nt_devicemode(&info
->devmode
);
2431 /* clean up all registry keys */
2434 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2435 SAFE_FREE( data
->keys
[i
].name
);
2436 regval_ctr_destroy( &data
->keys
[i
].values
);
2438 SAFE_FREE( data
->keys
);
2440 /* finally the top level structure */
2442 SAFE_FREE( *info_ptr
);
2446 /****************************************************************************
2447 ****************************************************************************/
2448 int unpack_devicemode(NT_DEVICEMODE
**nt_devmode
, char *buf
, int buflen
)
2452 NT_DEVICEMODE devmode
;
2454 ZERO_STRUCT(devmode
);
2456 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2458 if (!*nt_devmode
) return len
;
2460 len
+= tdb_unpack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2464 &devmode
.specversion
,
2465 &devmode
.driverversion
,
2467 &devmode
.driverextra
,
2468 &devmode
.orientation
,
2470 &devmode
.paperlength
,
2471 &devmode
.paperwidth
,
2474 &devmode
.defaultsource
,
2475 &devmode
.printquality
,
2478 &devmode
.yresolution
,
2484 &devmode
.bitsperpel
,
2486 &devmode
.pelsheight
,
2487 &devmode
.displayflags
,
2488 &devmode
.displayfrequency
,
2492 &devmode
.dithertype
,
2495 &devmode
.panningwidth
,
2496 &devmode
.panningheight
,
2499 if (devmode
.private) {
2500 /* the len in tdb_unpack is an int value and
2501 * devmode.driverextra is only a short
2503 len
+= tdb_unpack(buf
+len
, buflen
-len
, "B", &extra_len
, &devmode
.private);
2504 devmode
.driverextra
=(uint16
)extra_len
;
2506 /* check to catch an invalid TDB entry so we don't segfault */
2507 if (devmode
.driverextra
== 0) {
2508 devmode
.private = NULL
;
2512 *nt_devmode
= (NT_DEVICEMODE
*)memdup(&devmode
, sizeof(devmode
));
2514 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode
.devicename
, devmode
.formname
));
2515 if (devmode
.private)
2516 DEBUG(8,("with a private section of %d bytes\n", devmode
.driverextra
));
2521 /****************************************************************************
2522 Allocate and initialize a new slot.
2523 ***************************************************************************/
2525 static int add_new_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2530 if ( !data
|| !name
)
2533 /* allocate another slot in the NT_PRINTER_KEY array */
2535 d
= SMB_REALLOC_ARRAY( data
->keys
, NT_PRINTER_KEY
, data
->num_keys
+1);
2539 key_index
= data
->num_keys
;
2541 /* initialze new key */
2544 data
->keys
[key_index
].name
= SMB_STRDUP( name
);
2546 regval_ctr_init( &data
->keys
[key_index
].values
);
2548 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name
));
2553 /****************************************************************************
2554 search for a registry key name in the existing printer data
2555 ***************************************************************************/
2557 int lookup_printerkey( NT_PRINTER_DATA
*data
, const char *name
)
2562 if ( !data
|| !name
)
2565 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name
));
2567 /* loop over all existing keys */
2569 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2570 if ( strequal(data
->keys
[i
].name
, name
) ) {
2571 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name
));
2581 /****************************************************************************
2582 ***************************************************************************/
2584 uint32
get_printer_subkeys( NT_PRINTER_DATA
*data
, const char* key
, fstring
**subkeys
)
2588 int num_subkeys
= 0;
2590 fstring
*ptr
, *subkeys_ptr
= NULL
;
2596 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2597 if ( StrnCaseCmp(data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2598 /* match sure it is a subkey and not the key itself */
2600 key_len
= strlen( key
);
2601 if ( strlen(data
->keys
[i
].name
) == key_len
)
2604 /* get subkey path */
2606 p
= data
->keys
[i
].name
+ key_len
;
2609 fstrcpy( subkeyname
, p
);
2610 if ( (p
= strchr( subkeyname
, '\\' )) )
2613 /* don't add a key more than once */
2615 for ( j
=0; j
<num_subkeys
; j
++ ) {
2616 if ( strequal( subkeys_ptr
[j
], subkeyname
) )
2620 if ( j
!= num_subkeys
)
2623 /* found a match, so allocate space and copy the name */
2625 if ( !(ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
2626 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2628 SAFE_FREE( subkeys
);
2633 fstrcpy( subkeys_ptr
[num_subkeys
], subkeyname
);
2639 /* tag of the end */
2642 fstrcpy(subkeys_ptr
[num_subkeys
], "" );
2644 *subkeys
= subkeys_ptr
;
2650 static void map_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2653 smb_ucs2_t conv_str
[1024];
2656 regval_ctr_delvalue(ctr
, val_name
);
2657 str_size
= push_ucs2(NULL
, conv_str
, sz
, sizeof(conv_str
),
2658 STR_TERMINATE
| STR_NOALIGN
);
2659 regval_ctr_addvalue(ctr
, val_name
, REG_SZ
,
2660 (char *) conv_str
, str_size
);
2663 static void map_dword_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2666 regval_ctr_delvalue(ctr
, val_name
);
2667 regval_ctr_addvalue(ctr
, val_name
, REG_DWORD
,
2668 (char *) &dword
, sizeof(dword
));
2671 static void map_bool_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2674 uint8 bin_bool
= (b
? 1 : 0);
2675 regval_ctr_delvalue(ctr
, val_name
);
2676 regval_ctr_addvalue(ctr
, val_name
, REG_BINARY
,
2677 (char *) &bin_bool
, sizeof(bin_bool
));
2680 static void map_single_multi_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2681 const char *multi_sz
)
2683 smb_ucs2_t
*conv_strs
= NULL
;
2686 /* a multi-sz has to have a null string terminator, i.e., the last
2687 string must be followed by two nulls */
2688 str_size
= strlen(multi_sz
) + 2;
2689 conv_strs
= SMB_CALLOC_ARRAY(smb_ucs2_t
, str_size
);
2694 /* Change to byte units. */
2695 str_size
*= sizeof(smb_ucs2_t
);
2696 push_ucs2(NULL
, conv_strs
, multi_sz
, str_size
,
2697 STR_TERMINATE
| STR_NOALIGN
);
2699 regval_ctr_delvalue(ctr
, val_name
);
2700 regval_ctr_addvalue(ctr
, val_name
, REG_MULTI_SZ
,
2701 (char *) conv_strs
, str_size
);
2702 safe_free(conv_strs
);
2706 /****************************************************************************
2707 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2709 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2710 * @return BOOL indicating success or failure
2711 ***************************************************************************/
2713 static BOOL
map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2
*info2
)
2715 REGVAL_CTR
*ctr
= NULL
;
2718 char *allocated_string
= NULL
;
2719 const char *ascii_str
;
2722 if ((i
= lookup_printerkey(&info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2723 i
= add_new_printer_key(&info2
->data
, SPOOL_DSSPOOLER_KEY
);
2724 ctr
= &info2
->data
.keys
[i
].values
;
2726 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTERNAME
, info2
->sharename
);
2727 map_sz_into_ctr(ctr
, SPOOL_REG_SHORTSERVERNAME
, global_myname());
2729 /* we make the assumption that the netbios name is the same
2730 as the DNS name sinc ethe former will be what we used to
2733 if ( get_mydnsdomname( dnssuffix
) )
2734 fstr_sprintf( longname
, "%s.%s", global_myname(), dnssuffix
);
2736 fstrcpy( longname
, global_myname() );
2738 map_sz_into_ctr(ctr
, SPOOL_REG_SERVERNAME
, longname
);
2740 asprintf(&allocated_string
, "\\\\%s\\%s", longname
, info2
->sharename
);
2741 map_sz_into_ctr(ctr
, SPOOL_REG_UNCNAME
, allocated_string
);
2742 SAFE_FREE(allocated_string
);
2744 map_dword_into_ctr(ctr
, SPOOL_REG_VERSIONNUMBER
, 4);
2745 map_sz_into_ctr(ctr
, SPOOL_REG_DRIVERNAME
, info2
->drivername
);
2746 map_sz_into_ctr(ctr
, SPOOL_REG_LOCATION
, info2
->location
);
2747 map_sz_into_ctr(ctr
, SPOOL_REG_DESCRIPTION
, info2
->comment
);
2748 map_single_multi_sz_into_ctr(ctr
, SPOOL_REG_PORTNAME
, info2
->portname
);
2749 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSEPARATORFILE
, info2
->sepfile
);
2750 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTSTARTTIME
, info2
->starttime
);
2751 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTENDTIME
, info2
->untiltime
);
2752 map_dword_into_ctr(ctr
, SPOOL_REG_PRIORITY
, info2
->priority
);
2754 map_bool_into_ctr(ctr
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
2755 (info2
->attributes
&
2756 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
2758 switch (info2
->attributes
& 0x3) {
2760 ascii_str
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
2763 ascii_str
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
2766 ascii_str
= SPOOL_REGVAL_PRINTDIRECT
;
2769 ascii_str
= "unknown";
2771 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSPOOLING
, ascii_str
);
2776 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2
*info2
,
2780 REGVAL_CTR
*ctr
=NULL
;
2782 /* find the DsSpooler key */
2783 if ((i
= lookup_printerkey(&info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2784 i
= add_new_printer_key(&info2
->data
, SPOOL_DSSPOOLER_KEY
);
2785 ctr
= &info2
->data
.keys
[i
].values
;
2787 regval_ctr_delvalue(ctr
, "objectGUID");
2788 regval_ctr_addvalue(ctr
, "objectGUID", REG_BINARY
,
2789 (char *) &guid
, sizeof(struct uuid
));
2792 static WERROR
nt_printer_publish_ads(ADS_STRUCT
*ads
,
2793 NT_PRINTER_INFO_LEVEL
*printer
)
2797 char *prt_dn
= NULL
, *srv_dn
, *srv_cn_0
;
2798 char *srv_dn_utf8
, **srv_cn_utf8
;
2801 const char *attrs
[] = {"objectGUID", NULL
};
2803 WERROR win_rc
= WERR_OK
;
2805 DEBUG(5, ("publishing printer %s\n", printer
->info_2
->printername
));
2807 /* figure out where to publish */
2808 ads_find_machine_acct(ads
, &res
, global_myname());
2810 /* We use ldap_get_dn here as we need the answer
2811 * in utf8 to call ldap_explode_dn(). JRA. */
2813 srv_dn_utf8
= ldap_get_dn(ads
->ld
, res
);
2816 return WERR_SERVER_UNAVAILABLE
;
2818 ads_msgfree(ads
, res
);
2819 srv_cn_utf8
= ldap_explode_dn(srv_dn_utf8
, 1);
2821 ldap_memfree(srv_dn_utf8
);
2823 return WERR_SERVER_UNAVAILABLE
;
2825 /* Now convert to CH_UNIX. */
2826 if (pull_utf8_allocate(&srv_dn
, srv_dn_utf8
) == (size_t)-1) {
2827 ldap_memfree(srv_dn_utf8
);
2828 ldap_memfree(srv_cn_utf8
);
2830 return WERR_SERVER_UNAVAILABLE
;
2832 if (pull_utf8_allocate(&srv_cn_0
, srv_cn_utf8
[0]) == (size_t)-1) {
2833 ldap_memfree(srv_dn_utf8
);
2834 ldap_memfree(srv_cn_utf8
);
2837 return WERR_SERVER_UNAVAILABLE
;
2840 ldap_memfree(srv_dn_utf8
);
2841 ldap_memfree(srv_cn_utf8
);
2843 asprintf(&prt_dn
, "cn=%s-%s,%s", srv_cn_0
,
2844 printer
->info_2
->sharename
, srv_dn
);
2847 SAFE_FREE(srv_cn_0
);
2849 /* build the ads mods */
2850 ctx
= talloc_init("nt_printer_publish_ads");
2851 mods
= ads_init_mods(ctx
);
2853 get_local_printer_publishing_data(ctx
, &mods
,
2854 &printer
->info_2
->data
);
2855 ads_mod_str(ctx
, &mods
, SPOOL_REG_PRINTERNAME
,
2856 printer
->info_2
->sharename
);
2859 ads_rc
= ads_mod_printer_entry(ads
, prt_dn
, ctx
, &mods
);
2860 if (ads_rc
.err
.rc
== LDAP_NO_SUCH_OBJECT
)
2861 ads_rc
= ads_add_printer_entry(ads
, prt_dn
, ctx
, &mods
);
2863 if (!ADS_ERR_OK(ads_rc
))
2864 DEBUG(3, ("error publishing %s: %s\n", printer
->info_2
->sharename
, ads_errstr(ads_rc
)));
2866 talloc_destroy(ctx
);
2868 /* retreive the guid and store it locally */
2869 if (ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
2871 ads_pull_guid(ads
, res
, &guid
);
2872 ads_msgfree(ads
, res
);
2873 store_printer_guid(printer
->info_2
, guid
);
2874 win_rc
= mod_a_printer(printer
, 2);
2881 static WERROR
nt_printer_unpublish_ads(ADS_STRUCT
*ads
,
2882 NT_PRINTER_INFO_LEVEL
*printer
)
2886 char *prt_dn
= NULL
;
2888 DEBUG(5, ("unpublishing printer %s\n", printer
->info_2
->printername
));
2890 /* remove the printer from the directory */
2891 ads_rc
= ads_find_printer_on_server(ads
, &res
,
2892 printer
->info_2
->sharename
, global_myname());
2894 if (ADS_ERR_OK(ads_rc
) && ads_count_replies(ads
, res
)) {
2895 prt_dn
= ads_get_dn(ads
, res
);
2896 ads_rc
= ads_del_dn(ads
, prt_dn
);
2897 ads_memfree(ads
, prt_dn
);
2900 ads_msgfree(ads
, res
);
2904 /****************************************************************************
2905 * Publish a printer in the directory
2907 * @param snum describing printer service
2908 * @return WERROR indicating status of publishing
2909 ***************************************************************************/
2911 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
2914 ADS_STRUCT
*ads
= NULL
;
2915 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2918 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
2919 if (!W_ERROR_IS_OK(win_rc
))
2923 case SPOOL_DS_PUBLISH
:
2924 case SPOOL_DS_UPDATE
:
2925 /* set the DsSpooler info and attributes */
2926 if (!(map_nt_printer_info2_to_dsspooler(printer
->info_2
))) {
2927 win_rc
= WERR_NOMEM
;
2931 printer
->info_2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
2933 case SPOOL_DS_UNPUBLISH
:
2934 printer
->info_2
->attributes
^= PRINTER_ATTRIBUTE_PUBLISHED
;
2937 win_rc
= WERR_NOT_SUPPORTED
;
2941 win_rc
= mod_a_printer(printer
, 2);
2942 if (!W_ERROR_IS_OK(win_rc
)) {
2943 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc
)));
2947 ads
= ads_init(NULL
, NULL
, NULL
);
2949 DEBUG(3, ("ads_init() failed\n"));
2950 win_rc
= WERR_SERVER_UNAVAILABLE
;
2953 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
2954 SAFE_FREE(ads
->auth
.password
);
2955 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
2958 /* ads_connect() will find the DC for us */
2959 ads_rc
= ads_connect(ads
);
2960 if (!ADS_ERR_OK(ads_rc
)) {
2961 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
2962 win_rc
= WERR_ACCESS_DENIED
;
2967 case SPOOL_DS_PUBLISH
:
2968 case SPOOL_DS_UPDATE
:
2969 win_rc
= nt_printer_publish_ads(ads
, printer
);
2971 case SPOOL_DS_UNPUBLISH
:
2972 win_rc
= nt_printer_unpublish_ads(ads
, printer
);
2977 free_a_printer(&printer
, 2);
2982 WERROR
check_published_printers(void)
2985 ADS_STRUCT
*ads
= NULL
;
2987 int n_services
= lp_numservices();
2988 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2990 ads
= ads_init(NULL
, NULL
, NULL
);
2992 DEBUG(3, ("ads_init() failed\n"));
2993 return WERR_SERVER_UNAVAILABLE
;
2995 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
2996 SAFE_FREE(ads
->auth
.password
);
2997 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
3000 /* ads_connect() will find the DC for us */
3001 ads_rc
= ads_connect(ads
);
3002 if (!ADS_ERR_OK(ads_rc
)) {
3003 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
3005 return WERR_ACCESS_DENIED
;
3008 for (snum
= 0; snum
< n_services
; snum
++) {
3009 if (!(lp_snum_ok(snum
) && lp_print_ok(snum
)))
3012 if (W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2,
3013 lp_servicename(snum
))) &&
3014 (printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
))
3015 nt_printer_publish_ads(ads
, printer
);
3017 free_a_printer(&printer
, 2);
3024 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
,
3027 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3029 REGISTRY_VALUE
*guid_val
;
3033 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
3035 if (!W_ERROR_IS_OK(win_rc
) ||
3036 !(printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) ||
3037 ((i
= lookup_printerkey(&printer
->info_2
->data
,
3038 SPOOL_DSSPOOLER_KEY
)) < 0) ||
3039 !(ctr
= &printer
->info_2
->data
.keys
[i
].values
) ||
3040 !(guid_val
= regval_ctr_getvalue(ctr
, "objectGUID"))) {
3041 free_a_printer(&printer
, 2);
3045 /* fetching printer guids really ought to be a separate function.. */
3046 if (guid
&& regval_size(guid_val
) == sizeof(struct uuid
))
3047 memcpy(guid
, regval_data_p(guid_val
), sizeof(struct uuid
));
3049 free_a_printer(&printer
, 2);
3053 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
3058 WERROR
check_published_printers(void)
3063 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
,
3068 #endif /* HAVE_ADS */
3070 /****************************************************************************
3071 ***************************************************************************/
3073 WERROR
delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
)
3075 NT_PRINTER_DATA
*data
;
3077 int removed_keys
= 0;
3081 empty_slot
= data
->num_keys
;
3084 return WERR_INVALID_PARAM
;
3086 /* remove all keys */
3088 if ( !strlen(key
) ) {
3089 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3090 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3091 data
->keys
[i
].name
));
3093 SAFE_FREE( data
->keys
[i
].name
);
3094 regval_ctr_destroy( &data
->keys
[i
].values
);
3097 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3100 SAFE_FREE( data
->keys
);
3101 ZERO_STRUCTP( data
);
3106 /* remove a specific key (and all subkeys) */
3108 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3109 if ( StrnCaseCmp( data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
3110 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3111 data
->keys
[i
].name
));
3113 SAFE_FREE( data
->keys
[i
].name
);
3114 regval_ctr_destroy( &data
->keys
[i
].values
);
3116 /* mark the slot as empty */
3118 ZERO_STRUCTP( &data
->keys
[i
] );
3122 /* find the first empty slot */
3124 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3125 if ( !data
->keys
[i
].name
) {
3132 if ( i
== data
->num_keys
)
3133 /* nothing was removed */
3134 return WERR_INVALID_PARAM
;
3136 /* move everything down */
3138 for ( i
=empty_slot
+1; i
<data
->num_keys
; i
++ ) {
3139 if ( data
->keys
[i
].name
) {
3140 memcpy( &data
->keys
[empty_slot
], &data
->keys
[i
], sizeof(NT_PRINTER_KEY
) );
3141 ZERO_STRUCTP( &data
->keys
[i
] );
3149 data
->num_keys
-= removed_keys
;
3151 /* sanity check to see if anything is left */
3153 if ( !data
->num_keys
) {
3154 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2
->printername
));
3156 SAFE_FREE( data
->keys
);
3157 ZERO_STRUCTP( data
);
3163 /****************************************************************************
3164 ***************************************************************************/
3166 WERROR
delete_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3168 WERROR result
= WERR_OK
;
3171 /* we must have names on non-zero length */
3173 if ( !key
|| !*key
|| !value
|| !*value
)
3174 return WERR_INVALID_NAME
;
3176 /* find the printer key first */
3178 key_index
= lookup_printerkey( &p2
->data
, key
);
3179 if ( key_index
== -1 )
3182 /* make sure the value exists so we can return the correct error code */
3184 if ( !regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
) )
3185 return WERR_BADFILE
;
3187 regval_ctr_delvalue( &p2
->data
.keys
[key_index
].values
, value
);
3189 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3195 /****************************************************************************
3196 ***************************************************************************/
3198 WERROR
add_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
,
3199 uint32 type
, uint8
*data
, int real_len
)
3201 WERROR result
= WERR_OK
;
3204 /* we must have names on non-zero length */
3206 if ( !key
|| !*key
|| !value
|| !*value
)
3207 return WERR_INVALID_NAME
;
3209 /* find the printer key first */
3211 key_index
= lookup_printerkey( &p2
->data
, key
);
3212 if ( key_index
== -1 )
3213 key_index
= add_new_printer_key( &p2
->data
, key
);
3215 if ( key_index
== -1 )
3218 regval_ctr_addvalue( &p2
->data
.keys
[key_index
].values
, value
,
3219 type
, (const char *)data
, real_len
);
3221 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3222 key
, value
, type
, real_len
));
3227 /****************************************************************************
3228 ***************************************************************************/
3230 REGISTRY_VALUE
* get_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3234 if ( (key_index
= lookup_printerkey( &p2
->data
, key
)) == -1 )
3237 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3240 return regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
);
3243 /****************************************************************************
3244 Unpack a list of registry values frem the TDB
3245 ***************************************************************************/
3247 static int unpack_values(NT_PRINTER_DATA
*printer_data
, char *buf
, int buflen
)
3251 pstring string
, valuename
, keyname
;
3255 REGISTRY_VALUE
*regval_p
;
3258 /* add the "PrinterDriverData" key first for performance reasons */
3260 add_new_printer_key( printer_data
, SPOOL_PRINTERDATA_KEY
);
3262 /* loop and unpack the rest of the registry values */
3266 /* check to see if there are any more registry values */
3269 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", ®val_p
);
3273 /* unpack the next regval */
3275 len
+= tdb_unpack(buf
+len
, buflen
-len
, "fdB",
3282 * break of the keyname from the value name.
3283 * Valuenames can have embedded '\'s so be careful.
3284 * only support one level of keys. See the
3285 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3289 str
= strchr_m( string
, '\\');
3291 /* Put in "PrinterDriverData" is no key specified */
3294 pstrcpy( keyname
, SPOOL_PRINTERDATA_KEY
);
3295 pstrcpy( valuename
, string
);
3299 pstrcpy( keyname
, string
);
3300 pstrcpy( valuename
, str
+1 );
3303 /* see if we need a new key */
3305 if ( (key_index
=lookup_printerkey( printer_data
, keyname
)) == -1 )
3306 key_index
= add_new_printer_key( printer_data
, keyname
);
3308 if ( key_index
== -1 ) {
3309 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3314 /* add the new value */
3316 regval_ctr_addvalue( &printer_data
->keys
[key_index
].values
, valuename
, type
, (const char *)data_p
, size
);
3318 SAFE_FREE(data_p
); /* 'B' option to tdbpack does a malloc() */
3320 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname
, valuename
, size
));
3326 /****************************************************************************
3327 ***************************************************************************/
3329 static void map_to_os2_driver(fstring drivername
)
3331 static BOOL initialised
=False
;
3332 static fstring last_from
,last_to
;
3333 char *mapfile
= lp_os2_driver_map();
3334 char **lines
= NULL
;
3338 if (!strlen(drivername
))
3345 *last_from
= *last_to
= 0;
3349 if (strequal(drivername
,last_from
)) {
3350 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,last_to
));
3351 fstrcpy(drivername
,last_to
);
3355 lines
= file_lines_load(mapfile
, &numlines
);
3356 if (numlines
== 0) {
3357 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile
));
3361 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
3363 for( i
= 0; i
< numlines
; i
++) {
3364 char *nt_name
= lines
[i
];
3365 char *os2_name
= strchr(nt_name
,'=');
3372 while (isspace(*nt_name
))
3375 if (!*nt_name
|| strchr("#;",*nt_name
))
3379 int l
= strlen(nt_name
);
3380 while (l
&& isspace(nt_name
[l
-1])) {
3386 while (isspace(*os2_name
))
3390 int l
= strlen(os2_name
);
3391 while (l
&& isspace(os2_name
[l
-1])) {
3397 if (strequal(nt_name
,drivername
)) {
3398 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername
,os2_name
));
3399 fstrcpy(last_from
,drivername
);
3400 fstrcpy(last_to
,os2_name
);
3401 fstrcpy(drivername
,os2_name
);
3402 file_lines_free(lines
);
3407 file_lines_free(lines
);
3410 /****************************************************************************
3411 Get a default printer info 2 struct.
3412 ****************************************************************************/
3413 static WERROR
get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, const char *servername
, const char* sharename
)
3416 NT_PRINTER_INFO_LEVEL_2 info
;
3420 snum
= lp_servicenumber(sharename
);
3422 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", servername
);
3423 slprintf(info
.printername
, sizeof(info
.printername
)-1, "\\\\%s\\%s",
3424 servername
, sharename
);
3425 fstrcpy(info
.sharename
, sharename
);
3426 fstrcpy(info
.portname
, SAMBA_PRINTER_PORT_NAME
);
3428 /* by setting the driver name to an empty string, a local NT admin
3429 can now run the **local** APW to install a local printer driver
3430 for a Samba shared printer in 2.2. Without this, drivers **must** be
3431 installed on the Samba server for NT clients --jerry */
3432 #if 0 /* JERRY --do not uncomment-- */
3433 if (!*info
.drivername
)
3434 fstrcpy(info
.drivername
, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3438 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info
.drivername
));
3440 pstrcpy(info
.comment
, "");
3441 fstrcpy(info
.printprocessor
, "winprint");
3442 fstrcpy(info
.datatype
, "RAW");
3444 info
.attributes
= PRINTER_ATTRIBUTE_SAMBA
;
3446 info
.starttime
= 0; /* Minutes since 12:00am GMT */
3447 info
.untiltime
= 0; /* Minutes since 12:00am GMT */
3449 info
.default_priority
= 1;
3450 info
.setuptime
= (uint32
)time(NULL
);
3453 * I changed this as I think it is better to have a generic
3454 * DEVMODE than to crash Win2k explorer.exe --jerry
3455 * See the HP Deskjet 990c Win2k drivers for an example.
3457 * However the default devmode appears to cause problems
3458 * with the HP CLJ 8500 PCL driver. Hence the addition of
3459 * the "default devmode" parameter --jerry 22/01/2002
3462 if (lp_default_devmode(snum
)) {
3463 if ((info
.devmode
= construct_nt_devicemode(info
.printername
)) == NULL
)
3467 info
.devmode
= NULL
;
3470 /* This will get the current RPC talloc context, but we should be
3471 passing this as a parameter... fixme... JRA ! */
3473 if (!nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
))
3476 *info_ptr
= (NT_PRINTER_INFO_LEVEL_2
*)memdup(&info
, sizeof(info
));
3478 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3486 free_nt_devicemode(&info
.devmode
);
3487 return WERR_ACCESS_DENIED
;
3490 /****************************************************************************
3491 ****************************************************************************/
3492 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, const char *servername
, const char *sharename
)
3495 NT_PRINTER_INFO_LEVEL_2 info
;
3497 int snum
= lp_servicenumber(sharename
);
3498 TDB_DATA kbuf
, dbuf
;
3499 fstring printername
;
3500 char adevice
[MAXDEVICENAME
];
3504 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
3507 kbuf
.dsize
= strlen(key
)+1;
3509 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
3511 return get_a_printer_2_default(info_ptr
, servername
, sharename
);
3513 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "dddddddddddfffffPfffff",
3516 &info
.default_priority
,
3533 info
.printprocessor
,
3537 /* Samba has to have shared raw drivers. */
3538 info
.attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
3539 info
.attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
3541 /* Restore the stripped strings. */
3542 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", servername
);
3544 if ( lp_force_printername(snum
) )
3545 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, sharename
);
3547 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, info
.printername
);
3549 fstrcpy(info
.printername
, printername
);
3551 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3554 * Some client drivers freak out if there is a NULL devmode
3555 * (probably the driver is not checking before accessing
3556 * the devmode pointer) --jerry
3558 * See comments in get_a_printer_2_default()
3561 if (lp_default_devmode(snum
) && !info
.devmode
) {
3562 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3564 info
.devmode
= construct_nt_devicemode(printername
);
3567 slprintf( adevice
, sizeof(adevice
), "%s", info
.printername
);
3569 fstrcpy(info
.devmode
->devicename
, adevice
);
3572 len
+= unpack_values( &info
.data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3574 /* This will get the current RPC talloc context, but we should be
3575 passing this as a parameter... fixme... JRA ! */
3577 nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
);
3579 /* Fix for OS/2 drivers. */
3581 if (get_remote_arch() == RA_OS2
)
3582 map_to_os2_driver(info
.drivername
);
3584 SAFE_FREE(dbuf
.dptr
);
3585 *info_ptr
=memdup(&info
, sizeof(info
));
3587 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3588 sharename
, info
.printername
, info
.drivername
));
3593 /****************************************************************************
3594 Debugging function, dump at level 6 the struct in the logs.
3595 ****************************************************************************/
3596 static uint32
dump_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3599 NT_PRINTER_INFO_LEVEL_2
*info2
;
3601 DEBUG(106,("Dumping printer at level [%d]\n", level
));
3606 if (printer
->info_2
== NULL
)
3610 info2
=printer
->info_2
;
3612 DEBUGADD(106,("attributes:[%d]\n", info2
->attributes
));
3613 DEBUGADD(106,("priority:[%d]\n", info2
->priority
));
3614 DEBUGADD(106,("default_priority:[%d]\n", info2
->default_priority
));
3615 DEBUGADD(106,("starttime:[%d]\n", info2
->starttime
));
3616 DEBUGADD(106,("untiltime:[%d]\n", info2
->untiltime
));
3617 DEBUGADD(106,("status:[%d]\n", info2
->status
));
3618 DEBUGADD(106,("cjobs:[%d]\n", info2
->cjobs
));
3619 DEBUGADD(106,("averageppm:[%d]\n", info2
->averageppm
));
3620 DEBUGADD(106,("changeid:[%d]\n", info2
->changeid
));
3621 DEBUGADD(106,("c_setprinter:[%d]\n", info2
->c_setprinter
));
3622 DEBUGADD(106,("setuptime:[%d]\n", info2
->setuptime
));
3624 DEBUGADD(106,("servername:[%s]\n", info2
->servername
));
3625 DEBUGADD(106,("printername:[%s]\n", info2
->printername
));
3626 DEBUGADD(106,("sharename:[%s]\n", info2
->sharename
));
3627 DEBUGADD(106,("portname:[%s]\n", info2
->portname
));
3628 DEBUGADD(106,("drivername:[%s]\n", info2
->drivername
));
3629 DEBUGADD(106,("comment:[%s]\n", info2
->comment
));
3630 DEBUGADD(106,("location:[%s]\n", info2
->location
));
3631 DEBUGADD(106,("sepfile:[%s]\n", info2
->sepfile
));
3632 DEBUGADD(106,("printprocessor:[%s]\n", info2
->printprocessor
));
3633 DEBUGADD(106,("datatype:[%s]\n", info2
->datatype
));
3634 DEBUGADD(106,("parameters:[%s]\n", info2
->parameters
));
3640 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level
));
3648 /****************************************************************************
3649 Update the changeid time.
3650 This is SO NASTY as some drivers need this to change, others need it
3651 static. This value will change every second, and I must hope that this
3652 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3654 ****************************************************************************/
3656 static uint32
rev_changeid(void)
3660 get_process_uptime(&tv
);
3663 /* Return changeid as msec since spooler restart */
3664 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
3667 * This setting seems to work well but is too untested
3668 * to replace the above calculation. Left in for experiementation
3669 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3671 return tv
.tv_sec
* 10 + tv
.tv_usec
/ 100000;
3675 /********************************************************************
3676 Send a message to all smbds about the printer that just changed
3677 ********************************************************************/
3679 static BOOL
send_printer_mod_msg( char* printername
)
3681 int len
= strlen(printername
);
3686 DEBUG(10,("send_printer_mod_msg: Sending message about printer change [%s]\n",
3689 /* spam everyone that we just changed this printer */
3691 message_send_all( conn_tdb_ctx(), MSG_PRINTER_MOD
, printername
, len
+1, False
, NULL
);
3697 * The function below are the high level ones.
3698 * only those ones must be called from the spoolss code.
3702 /****************************************************************************
3703 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3704 ****************************************************************************/
3706 WERROR
mod_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3710 dump_a_printer(printer
, level
);
3713 * invalidate cache for all open handles to this printer.
3714 * cache for a given handle will be updated on the next
3718 invalidate_printer_hnd_cache( printer
->info_2
->sharename
);
3719 send_printer_mod_msg( printer
->info_2
->sharename
);
3725 * Update the changestamp. Emperical tests show that the
3726 * ChangeID is always updated,but c_setprinter is
3727 * global spooler variable (not per printer).
3730 /* ChangeID **must** be increasing over the lifetime
3731 of client's spoolss service in order for the
3732 client's cache to show updates */
3734 printer
->info_2
->changeid
= rev_changeid();
3737 * Because one day someone will ask:
3738 * NT->NT An admin connection to a remote
3739 * printer show changes imeediately in
3740 * the properities dialog
3742 * A non-admin connection will only show the
3743 * changes after viewing the properites page
3744 * 2 times. Seems to be related to a
3745 * race condition in the client between the spooler
3746 * updating the local cache and the Explorer.exe GUI
3747 * actually displaying the properties.
3749 * This is fixed in Win2k. admin/non-admin
3750 * connections both display changes immediately.
3755 result
=update_a_printer_2(printer
->info_2
);
3760 result
=WERR_UNKNOWN_LEVEL
;
3767 /****************************************************************************
3768 Initialize printer devmode & data with previously saved driver init values.
3769 ****************************************************************************/
3771 static BOOL
set_driver_init_2( NT_PRINTER_INFO_LEVEL_2
*info_ptr
)
3775 TDB_DATA kbuf
, dbuf
;
3776 NT_PRINTER_INFO_LEVEL_2 info
;
3782 * Delete any printer data 'values' already set. When called for driver
3783 * replace, there will generally be some, but during an add printer, there
3784 * should not be any (if there are delete them).
3787 delete_all_printer_data( info_ptr
, "" );
3789 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info_ptr
->drivername
);
3792 kbuf
.dsize
= strlen(key
)+1;
3794 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
3797 * When changing to a driver that has no init info in the tdb, remove
3798 * the previous drivers init info and leave the new on blank.
3800 free_nt_devicemode(&info_ptr
->devmode
);
3805 * Get the saved DEVMODE..
3808 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3811 * The saved DEVMODE contains the devicename from the printer used during
3812 * the initialization save. Change it to reflect the new printer.
3815 if ( info
.devmode
) {
3816 ZERO_STRUCT(info
.devmode
->devicename
);
3817 fstrcpy(info
.devmode
->devicename
, info_ptr
->printername
);
3821 * NT/2k does not change out the entire DeviceMode of a printer
3822 * when changing the driver. Only the driverextra, private, &
3823 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3825 * Later examination revealed that Windows NT/2k does reset the
3826 * the printer's device mode, bit **only** when you change a
3827 * property of the device mode such as the page orientation.
3832 /* Bind the saved DEVMODE to the new the printer */
3834 free_nt_devicemode(&info_ptr
->devmode
);
3835 info_ptr
->devmode
= info
.devmode
;
3837 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3838 info_ptr
->printername
, info_ptr
->devmode
?"VALID":"NULL", info_ptr
->drivername
));
3840 /* Add the printer data 'values' to the new printer */
3842 len
+= unpack_values( &info_ptr
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3845 SAFE_FREE(dbuf
.dptr
);
3850 /****************************************************************************
3851 Initialize printer devmode & data with previously saved driver init values.
3852 When a printer is created using AddPrinter, the drivername bound to the
3853 printer is used to lookup previously saved driver initialization info, which
3854 is bound to the new printer.
3855 ****************************************************************************/
3857 BOOL
set_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3859 BOOL result
= False
;
3863 result
= set_driver_init_2(printer
->info_2
);
3867 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3875 /****************************************************************************
3876 Delete driver init data stored for a specified driver
3877 ****************************************************************************/
3879 BOOL
del_driver_init(char *drivername
)
3884 if (!drivername
|| !*drivername
) {
3885 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3889 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, drivername
);
3892 kbuf
.dsize
= strlen(key
)+1;
3894 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername
));
3896 return (tdb_delete(tdb_drivers
, kbuf
) == 0);
3899 /****************************************************************************
3900 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3901 in the tdb. Note: this is different from the driver entry and the printer
3902 entry. There should be a single driver init entry for each driver regardless
3903 of whether it was installed from NT or 2K. Technically, they should be
3904 different, but they work out to the same struct.
3905 ****************************************************************************/
3907 static uint32
update_driver_init_2(NT_PRINTER_INFO_LEVEL_2
*info
)
3911 int buflen
, len
, ret
;
3912 TDB_DATA kbuf
, dbuf
;
3919 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
3921 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
3926 tb
= (char *)SMB_REALLOC(buf
, len
);
3928 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3938 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info
->drivername
);
3941 kbuf
.dsize
= strlen(key
)+1;
3945 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
3949 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3953 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3954 info
->sharename
, info
->drivername
));
3959 /****************************************************************************
3960 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3961 ****************************************************************************/
3963 static uint32
update_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3967 dump_a_printer(printer
, level
);
3971 result
= update_driver_init_2(printer
->info_2
);
3981 /****************************************************************************
3982 Convert the printer data value, a REG_BINARY array, into an initialization
3983 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3984 got to keep the endians happy :).
3985 ****************************************************************************/
3987 static BOOL
convert_driver_init( TALLOC_CTX
*ctx
, NT_DEVICEMODE
*nt_devmode
, uint8
*data
, uint32 data_len
)
3989 BOOL result
= False
;
3993 ZERO_STRUCT(devmode
);
3995 prs_init(&ps
, 0, ctx
, UNMARSHALL
);
3996 ps
.data_p
= (char *)data
;
3997 ps
.buffer_size
= data_len
;
3999 if (spoolss_io_devmode("phantom DEVMODE", &ps
, 0, &devmode
))
4000 result
= convert_devicemode("", &devmode
, &nt_devmode
);
4002 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4007 /****************************************************************************
4008 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4010 1. Use the driver's config DLL to this UNC printername and:
4011 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4012 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4013 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4015 The last step triggers saving the "driver initialization" information for
4016 this printer into the tdb. Later, new printers that use this driver will
4017 have this initialization information bound to them. This simulates the
4018 driver initialization, as if it had run on the Samba server (as it would
4021 The Win32 client side code requirement sucks! But until we can run arbitrary
4022 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4024 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4025 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4026 about it and you will realize why. JRR 010720
4027 ****************************************************************************/
4029 static WERROR
save_driver_init_2(NT_PRINTER_INFO_LEVEL
*printer
, uint8
*data
, uint32 data_len
)
4031 WERROR status
= WERR_OK
;
4032 TALLOC_CTX
*ctx
= NULL
;
4033 NT_DEVICEMODE
*nt_devmode
= NULL
;
4034 NT_DEVICEMODE
*tmp_devmode
= printer
->info_2
->devmode
;
4037 * When the DEVMODE is already set on the printer, don't try to unpack it.
4039 DEBUG(8,("save_driver_init_2: Enter...\n"));
4041 if ( !printer
->info_2
->devmode
&& data_len
) {
4043 * Set devmode on printer info, so entire printer initialization can be
4047 if ((ctx
= talloc_init("save_driver_init_2")) == NULL
)
4050 if ((nt_devmode
= SMB_MALLOC_P(NT_DEVICEMODE
)) == NULL
) {
4051 status
= WERR_NOMEM
;
4055 ZERO_STRUCTP(nt_devmode
);
4058 * The DEVMODE is held in the 'data' component of the param in raw binary.
4059 * Convert it to to a devmode structure
4061 if ( !convert_driver_init( ctx
, nt_devmode
, data
, data_len
)) {
4062 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4063 status
= WERR_INVALID_PARAM
;
4067 printer
->info_2
->devmode
= nt_devmode
;
4071 * Pack up and add (or update) the DEVMODE and any current printer data to
4072 * a 'driver init' element in the tdb
4076 if ( update_driver_init(printer
, 2) != 0 ) {
4077 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4078 status
= WERR_NOMEM
;
4083 * If driver initialization info was successfully saved, set the current
4084 * printer to match it. This allows initialization of the current printer
4085 * as well as the driver.
4087 status
= mod_a_printer(printer
, 2);
4088 if (!W_ERROR_IS_OK(status
)) {
4089 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4090 printer
->info_2
->printername
));
4094 talloc_destroy(ctx
);
4095 free_nt_devicemode( &nt_devmode
);
4097 printer
->info_2
->devmode
= tmp_devmode
;
4102 /****************************************************************************
4103 Update the driver init info (DEVMODE and specifics) for a printer
4104 ****************************************************************************/
4106 WERROR
save_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
, uint8
*data
, uint32 data_len
)
4108 WERROR status
= WERR_OK
;
4112 status
= save_driver_init_2( printer
, data
, data_len
);
4115 status
= WERR_UNKNOWN_LEVEL
;
4122 /****************************************************************************
4123 Deep copy a NT_PRINTER_DATA
4124 ****************************************************************************/
4126 static NTSTATUS
copy_printer_data( NT_PRINTER_DATA
*dst
, NT_PRINTER_DATA
*src
)
4128 int i
, j
, num_vals
, new_key_index
;
4129 REGVAL_CTR
*src_key
, *dst_key
;
4132 return NT_STATUS_NO_MEMORY
;
4134 for ( i
=0; i
<src
->num_keys
; i
++ ) {
4136 /* create a new instance of the printerkey in the destination
4137 printer_data object */
4139 new_key_index
= add_new_printer_key( dst
, src
->keys
[i
].name
);
4140 dst_key
= &dst
->keys
[new_key_index
].values
;
4142 src_key
= &src
->keys
[i
].values
;
4143 num_vals
= regval_ctr_numvals( src_key
);
4145 /* dup the printer entire printer key */
4147 for ( j
=0; j
<num_vals
; j
++ ) {
4148 regval_ctr_copyvalue( dst_key
, regval_ctr_specific_value(src_key
, j
) );
4152 return NT_STATUS_OK
;
4155 /****************************************************************************
4156 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
4158 ****************************************************************************/
4160 NT_PRINTER_INFO_LEVEL_2
* dup_printer_2( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL_2
*printer
)
4162 NT_PRINTER_INFO_LEVEL_2
*copy
;
4167 if ( !(copy
= SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL_2
)) )
4170 memcpy( copy
, printer
, sizeof(NT_PRINTER_INFO_LEVEL_2
) );
4172 /* malloc()'d members copied here */
4174 copy
->devmode
= dup_nt_devicemode( printer
->devmode
);
4176 ZERO_STRUCT( copy
->data
);
4177 copy_printer_data( ©
->data
, &printer
->data
);
4179 /* this is talloc()'d; very ugly that we have a structure that
4180 is half malloc()'d and half talloc()'d but that is the way
4181 that the PRINTER_INFO stuff is written right now. --jerry */
4183 copy
->secdesc_buf
= dup_sec_desc_buf( ctx
, printer
->secdesc_buf
);
4188 /****************************************************************************
4189 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4191 Previously the code had a memory allocation problem because it always
4192 used the TALLOC_CTX from the Printer_entry*. This context lasts
4193 as a long as the original handle is open. So if the client made a lot
4194 of getprinter[data]() calls, the memory usage would climb. Now we use
4195 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4196 still use the Printer_entry->ctx for maintaining the cache copy though
4197 since that object must live as long as the handle by definition.
4200 ****************************************************************************/
4202 WERROR
get_a_printer( Printer_entry
*print_hnd
, NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
,
4203 const char *sharename
)
4206 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4211 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename
, (unsigned int)level
));
4215 if ((printer
= SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL
)) == NULL
) {
4216 DEBUG(0,("get_a_printer: malloc fail.\n"));
4219 ZERO_STRUCTP(printer
);
4222 fstrcpy( servername
, print_hnd
->servername
);
4224 fstrcpy( servername
, "%L" );
4225 standard_sub_basic( "", servername
, sizeof(servername
)-1 );
4229 * check for cache first. A Printer handle cannot changed
4230 * to another printer object so we only check that the printer
4231 * is actually for a printer and that the printer_info pointer
4235 && (print_hnd
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)
4236 && print_hnd
->printer_info
)
4238 /* get_talloc_ctx() works here because we need a short
4239 lived talloc context */
4241 if ( !(printer
->info_2
= dup_printer_2(get_talloc_ctx(), print_hnd
->printer_info
->info_2
)) )
4243 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
4249 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
4251 *pp_printer
= printer
;
4257 /* no cache for this handle; see if we can match one from another handle.
4258 Make sure to use a short lived talloc ctx */
4261 result
= find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer
->info_2
, servername
, sharename
);
4263 /* fail to disk if we don't have it with any open handle */
4265 if ( !print_hnd
|| !W_ERROR_IS_OK(result
) )
4266 result
= get_a_printer_2(&printer
->info_2
, servername
, sharename
);
4268 /* we have a new printer now. Save it with this handle */
4270 if ( W_ERROR_IS_OK(result
) ) {
4271 dump_a_printer(printer
, level
);
4273 /* save a copy in cache */
4274 if ( print_hnd
&& (print_hnd
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)) {
4275 if ( !print_hnd
->printer_info
)
4276 print_hnd
->printer_info
= SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL
);
4278 if ( print_hnd
->printer_info
) {
4279 /* make sure to use the handle's talloc ctx here since
4280 the printer_2 object must last until the handle is closed */
4282 print_hnd
->printer_info
->info_2
= dup_printer_2(print_hnd
->ctx
, printer
->info_2
);
4284 /* don't fail the lookup just because the cache update failed */
4285 if ( !print_hnd
->printer_info
->info_2
)
4286 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4289 *pp_printer
= printer
;
4297 result
=WERR_UNKNOWN_LEVEL
;
4301 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename
, (unsigned int)level
, dos_errstr(result
)));
4306 /****************************************************************************
4307 Deletes a NT_PRINTER_INFO_LEVEL struct.
4308 ****************************************************************************/
4310 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
4313 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
4315 DEBUG(104,("freeing a printer at level [%d]\n", level
));
4317 if (printer
== NULL
)
4322 if (printer
->info_2
!= NULL
) {
4323 free_nt_printer_info_level_2(&printer
->info_2
);
4334 SAFE_FREE(*pp_printer
);
4338 /****************************************************************************
4339 ****************************************************************************/
4340 uint32
add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4343 DEBUG(104,("adding a printer at level [%d]\n", level
));
4344 dump_a_printer_driver(driver
, level
);
4348 result
=add_a_printer_driver_3(driver
.info_3
);
4352 result
=add_a_printer_driver_6(driver
.info_6
);
4362 /****************************************************************************
4363 ****************************************************************************/
4365 WERROR
get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL
*driver
, uint32 level
,
4366 fstring drivername
, const char *architecture
, uint32 version
)
4372 /* Sometime we just want any version of the driver */
4374 if ( version
== DRIVER_ANY_VERSION
) {
4375 /* look for Win2k first and then for NT4 */
4376 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4379 if ( !W_ERROR_IS_OK(result
) ) {
4380 result
= get_a_printer_driver_3( &driver
->info_3
,
4381 drivername
, architecture
, 2 );
4384 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4385 architecture
, version
);
4394 if (W_ERROR_IS_OK(result
))
4395 dump_a_printer_driver(*driver
, level
);
4400 /****************************************************************************
4401 ****************************************************************************/
4402 uint32
free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4409 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
4410 if (driver
.info_3
!= NULL
)
4412 info3
=driver
.info_3
;
4413 SAFE_FREE(info3
->dependentfiles
);
4414 ZERO_STRUCTP(info3
);
4424 NT_PRINTER_DRIVER_INFO_LEVEL_6
*info6
;
4425 if (driver
.info_6
!= NULL
) {
4426 info6
=driver
.info_6
;
4427 SAFE_FREE(info6
->dependentfiles
);
4428 SAFE_FREE(info6
->previousnames
);
4429 ZERO_STRUCTP(info6
);
4445 /****************************************************************************
4446 Determine whether or not a particular driver is currently assigned
4448 ****************************************************************************/
4450 BOOL
printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
)
4453 int n_services
= lp_numservices();
4454 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4455 BOOL in_use
= False
;
4460 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4462 /* loop through the printers.tdb and check for the drivername */
4464 for (snum
=0; snum
<n_services
&& !in_use
; snum
++) {
4465 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
4468 if ( !W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))) )
4471 if ( strequal(info_3
->name
, printer
->info_2
->drivername
) )
4474 free_a_printer( &printer
, 2 );
4477 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4480 NT_PRINTER_DRIVER_INFO_LEVEL d
;
4483 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3
->name
));
4485 /* we can still remove the driver if there is one of
4486 "Windows NT x86" version 2 or 3 left */
4488 if ( !strequal( "Windows NT x86", info_3
->environment
) ) {
4489 werr
= get_a_printer_driver( &d
, 3, info_3
->name
, "Windows NT x86", DRIVER_ANY_VERSION
);
4492 switch ( info_3
->cversion
) {
4494 werr
= get_a_printer_driver( &d
, 3, info_3
->name
, "Windows NT x86", 3 );
4497 werr
= get_a_printer_driver( &d
, 3, info_3
->name
, "Windows NT x86", 2 );
4500 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4502 werr
= WERR_UNKNOWN_PRINTER_DRIVER
;
4507 /* now check the error code */
4509 if ( W_ERROR_IS_OK(werr
) ) {
4510 /* it's ok to remove the driver, we have other architctures left */
4512 free_a_printer_driver( d
, 3 );
4516 /* report that the driver is not in use by default */
4522 /**********************************************************************
4523 Check to see if a ogiven file is in use by *info
4524 *********************************************************************/
4526 static BOOL
drv_file_in_use( char* file
, NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4533 if ( strequal(file
, info
->driverpath
) )
4536 if ( strequal(file
, info
->datafile
) )
4539 if ( strequal(file
, info
->configfile
) )
4542 if ( strequal(file
, info
->helpfile
) )
4545 /* see of there are any dependent files to examine */
4547 if ( !info
->dependentfiles
)
4550 while ( *info
->dependentfiles
[i
] ) {
4551 if ( strequal(file
, info
->dependentfiles
[i
]) )
4560 /**********************************************************************
4561 Utility function to remove the dependent file pointed to by the
4562 input parameter from the list
4563 *********************************************************************/
4565 static void trim_dependent_file( fstring files
[], int idx
)
4568 /* bump everything down a slot */
4570 while( *files
[idx
+1] ) {
4571 fstrcpy( files
[idx
], files
[idx
+1] );
4580 /**********************************************************************
4581 Check if any of the files used by src are also used by drv
4582 *********************************************************************/
4584 static BOOL
trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*src
,
4585 NT_PRINTER_DRIVER_INFO_LEVEL_3
*drv
)
4587 BOOL in_use
= False
;
4593 /* check each file. Remove it from the src structure if it overlaps */
4595 if ( drv_file_in_use(src
->driverpath
, drv
) ) {
4597 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driverpath
));
4598 fstrcpy( src
->driverpath
, "" );
4601 if ( drv_file_in_use(src
->datafile
, drv
) ) {
4603 DEBUG(10,("Removing datafile [%s] from list\n", src
->datafile
));
4604 fstrcpy( src
->datafile
, "" );
4607 if ( drv_file_in_use(src
->configfile
, drv
) ) {
4609 DEBUG(10,("Removing configfile [%s] from list\n", src
->configfile
));
4610 fstrcpy( src
->configfile
, "" );
4613 if ( drv_file_in_use(src
->helpfile
, drv
) ) {
4615 DEBUG(10,("Removing helpfile [%s] from list\n", src
->helpfile
));
4616 fstrcpy( src
->helpfile
, "" );
4619 /* are there any dependentfiles to examine? */
4621 if ( !src
->dependentfiles
)
4624 while ( *src
->dependentfiles
[i
] ) {
4625 if ( drv_file_in_use(src
->dependentfiles
[i
], drv
) ) {
4627 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependentfiles
[i
]));
4628 trim_dependent_file( src
->dependentfiles
, i
);
4636 /****************************************************************************
4637 Determine whether or not a particular driver files are currently being
4638 used by any other driver.
4640 Return value is True if any files were in use by other drivers
4641 and False otherwise.
4643 Upon return, *info has been modified to only contain the driver files
4644 which are not in use
4645 ****************************************************************************/
4647 BOOL
printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4652 fstring
*list
= NULL
;
4653 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4658 version
= info
->cversion
;
4660 /* loop over all driver versions */
4662 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4664 /* get the list of drivers */
4667 ndrivers
= get_ntdrivers(&list
, info
->environment
, version
);
4669 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4670 ndrivers
, info
->environment
, version
));
4672 /* check each driver for overlap in files */
4674 for (i
=0; i
<ndrivers
; i
++) {
4675 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
4677 ZERO_STRUCT(driver
);
4679 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, list
[i
], info
->environment
, version
)) ) {
4684 /* check if d2 uses any files from d1 */
4685 /* only if this is a different driver than the one being deleted */
4687 if ( !strequal(info
->name
, driver
.info_3
->name
) ) {
4688 if ( trim_overlap_drv_files(info
, driver
.info_3
) ) {
4689 free_a_printer_driver(driver
, 3);
4695 free_a_printer_driver(driver
, 3);
4700 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4702 driver
.info_3
= info
;
4704 if ( DEBUGLEVEL
>= 20 )
4705 dump_a_printer_driver( driver
, 3 );
4710 /****************************************************************************
4711 Actually delete the driver files. Make sure that
4712 printer_driver_files_in_use() return False before calling
4714 ****************************************************************************/
4716 static BOOL
delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
)
4720 connection_struct
*conn
;
4730 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3
->name
, info_3
->cversion
));
4733 * Connect to the print$ share under the same account as the
4734 * user connected to the rpc pipe. Note we must be root to
4738 null_pw
= data_blob( NULL
, 0 );
4739 fstrcpy(res_type
, "A:");
4741 conn
= make_connection_with_chdir( "print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
4745 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4749 /* Save who we are - we are temporarily becoming the connection user. */
4751 if ( !become_user(conn
, conn
->vuid
) ) {
4752 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4756 /* now delete the files; must strip the '\print$' string from
4759 if ( *info_3
->driverpath
) {
4760 if ( (s
= strchr( &info_3
->driverpath
[1], '\\' )) != NULL
) {
4761 driver_unix_convert(s
, conn
, NULL
, &bad_path
, &st
);
4762 DEBUG(10,("deleting driverfile [%s]\n", s
));
4763 unlink_internals(conn
, 0, s
);
4767 if ( *info_3
->configfile
) {
4768 if ( (s
= strchr( &info_3
->configfile
[1], '\\' )) != NULL
) {
4769 driver_unix_convert(s
, conn
, NULL
, &bad_path
, &st
);
4770 DEBUG(10,("deleting configfile [%s]\n", s
));
4771 unlink_internals(conn
, 0, s
);
4775 if ( *info_3
->datafile
) {
4776 if ( (s
= strchr( &info_3
->datafile
[1], '\\' )) != NULL
) {
4777 driver_unix_convert(s
, conn
, NULL
, &bad_path
, &st
);
4778 DEBUG(10,("deleting datafile [%s]\n", s
));
4779 unlink_internals(conn
, 0, s
);
4783 if ( *info_3
->helpfile
) {
4784 if ( (s
= strchr( &info_3
->helpfile
[1], '\\' )) != NULL
) {
4785 driver_unix_convert(s
, conn
, NULL
, &bad_path
, &st
);
4786 DEBUG(10,("deleting helpfile [%s]\n", s
));
4787 unlink_internals(conn
, 0, s
);
4791 /* check if we are done removing files */
4793 if ( info_3
->dependentfiles
) {
4794 while ( *info_3
->dependentfiles
[i
] ) {
4797 /* bypass the "\print$" portion of the path */
4799 if ( (file
= strchr( info_3
->dependentfiles
[i
]+1, '\\' )) != NULL
) {
4800 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4801 DEBUG(10,("deleting dependent file [%s]\n", file
));
4802 unlink_internals(conn
, 0, file
);
4814 /****************************************************************************
4815 Remove a printer driver from the TDB. This assumes that the the driver was
4816 previously looked up.
4817 ***************************************************************************/
4819 WERROR
delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
,
4820 uint32 version
, BOOL delete_files
)
4824 TDB_DATA kbuf
, dbuf
;
4825 NT_PRINTER_DRIVER_INFO_LEVEL ctr
;
4827 /* delete the tdb data first */
4829 arch
= get_short_archi(info_3
->environment
);
4830 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
,
4831 arch
, version
, info_3
->name
);
4833 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4834 key
, delete_files
? "TRUE" : "FALSE" ));
4836 ctr
.info_3
= info_3
;
4837 dump_a_printer_driver( ctr
, 3 );
4840 kbuf
.dsize
=strlen(key
)+1;
4842 /* check if the driver actually exists for this environment */
4844 dbuf
= tdb_fetch( tdb_drivers
, kbuf
);
4846 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key
));
4847 return WERR_UNKNOWN_PRINTER_DRIVER
;
4850 SAFE_FREE( dbuf
.dptr
);
4852 /* ok... the driver exists so the delete should return success */
4854 if (tdb_delete(tdb_drivers
, kbuf
) == -1) {
4855 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key
));
4856 return WERR_ACCESS_DENIED
;
4860 * now delete any associated files if delete_files == True
4861 * even if this part failes, we return succes because the
4862 * driver doesn not exist any more
4866 delete_driver_files( info_3
, user
);
4869 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key
));
4874 /****************************************************************************
4875 Store a security desc for a printer.
4876 ****************************************************************************/
4878 WERROR
nt_printing_setsec(const char *printername
, SEC_DESC_BUF
*secdesc_ctr
)
4880 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4881 SEC_DESC_BUF
*old_secdesc_ctr
= NULL
;
4883 TALLOC_CTX
*mem_ctx
= NULL
;
4887 mem_ctx
= talloc_init("nt_printing_setsec");
4888 if (mem_ctx
== NULL
)
4891 /* The old owner and group sids of the security descriptor are not
4892 present when new ACEs are added or removed by changing printer
4893 permissions through NT. If they are NULL in the new security
4894 descriptor then copy them over from the old one. */
4896 if (!secdesc_ctr
->sec
->owner_sid
|| !secdesc_ctr
->sec
->grp_sid
) {
4897 DOM_SID
*owner_sid
, *group_sid
;
4898 SEC_ACL
*dacl
, *sacl
;
4899 SEC_DESC
*psd
= NULL
;
4902 nt_printing_getsec(mem_ctx
, printername
, &old_secdesc_ctr
);
4904 /* Pick out correct owner and group sids */
4906 owner_sid
= secdesc_ctr
->sec
->owner_sid
?
4907 secdesc_ctr
->sec
->owner_sid
:
4908 old_secdesc_ctr
->sec
->owner_sid
;
4910 group_sid
= secdesc_ctr
->sec
->grp_sid
?
4911 secdesc_ctr
->sec
->grp_sid
:
4912 old_secdesc_ctr
->sec
->grp_sid
;
4914 dacl
= secdesc_ctr
->sec
->dacl
?
4915 secdesc_ctr
->sec
->dacl
:
4916 old_secdesc_ctr
->sec
->dacl
;
4918 sacl
= secdesc_ctr
->sec
->sacl
?
4919 secdesc_ctr
->sec
->sacl
:
4920 old_secdesc_ctr
->sec
->sacl
;
4922 /* Make a deep copy of the security descriptor */
4924 psd
= make_sec_desc(mem_ctx
, secdesc_ctr
->sec
->revision
, secdesc_ctr
->sec
->type
,
4925 owner_sid
, group_sid
,
4930 new_secdesc_ctr
= make_sec_desc_buf(mem_ctx
, size
, psd
);
4933 if (!new_secdesc_ctr
) {
4934 new_secdesc_ctr
= secdesc_ctr
;
4937 /* Store the security descriptor in a tdb */
4939 prs_init(&ps
, (uint32
)sec_desc_size(new_secdesc_ctr
->sec
) +
4940 sizeof(SEC_DESC_BUF
), mem_ctx
, MARSHALL
);
4942 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr
,
4944 status
= WERR_BADFUNC
;
4948 slprintf(key
, sizeof(key
)-1, "SECDESC/%s", printername
);
4950 if (tdb_prs_store(tdb_printers
, key
, &ps
)==0) {
4953 DEBUG(1,("Failed to store secdesc for %s\n", printername
));
4954 status
= WERR_BADFUNC
;
4957 /* Free malloc'ed memory */
4963 talloc_destroy(mem_ctx
);
4967 /****************************************************************************
4968 Construct a default security descriptor buffer for a printer.
4969 ****************************************************************************/
4971 static SEC_DESC_BUF
*construct_default_printer_sdb(TALLOC_CTX
*ctx
)
4973 SEC_ACE ace
[5]; /* max number of ace entries */
4976 SEC_ACL
*psa
= NULL
;
4977 SEC_DESC_BUF
*sdb
= NULL
;
4978 SEC_DESC
*psd
= NULL
;
4982 /* Create an ACE where Everyone is allowed to print */
4984 init_sec_access(&sa
, PRINTER_ACE_PRINT
);
4985 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
4986 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4988 /* Add the domain admins group if we are a DC */
4991 DOM_SID domadmins_sid
;
4993 sid_copy(&domadmins_sid
, get_global_sam_sid());
4994 sid_append_rid(&domadmins_sid
, DOMAIN_GROUP_RID_ADMINS
);
4996 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
4997 init_sec_ace(&ace
[i
++], &domadmins_sid
,
4998 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
4999 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5000 init_sec_ace(&ace
[i
++], &domadmins_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5001 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5003 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid
)) {
5004 sid_append_rid(&adm_sid
, DOMAIN_USER_RID_ADMIN
);
5006 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
5007 init_sec_ace(&ace
[i
++], &adm_sid
,
5008 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5009 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5010 init_sec_ace(&ace
[i
++], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5011 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5014 /* add BUILTIN\Administrators as FULL CONTROL */
5016 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
5017 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
5018 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5019 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5020 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
5021 SEC_ACE_TYPE_ACCESS_ALLOWED
,
5022 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5024 /* Make the security descriptor owned by the BUILTIN\Administrators */
5026 /* The ACL revision number in rpc_secdesc.h differs from the one
5027 created by NT when setting ACE entries in printer
5028 descriptors. NT4 complains about the property being edited by a
5031 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, i
, ace
)) != NULL
) {
5032 psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
5033 &global_sid_Builtin_Administrators
,
5034 &global_sid_Builtin_Administrators
,
5035 NULL
, psa
, &sd_size
);
5039 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5043 sdb
= make_sec_desc_buf(ctx
, sd_size
, psd
);
5045 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5046 (unsigned int)sd_size
));
5051 /****************************************************************************
5052 Get a security desc for a printer.
5053 ****************************************************************************/
5055 BOOL
nt_printing_getsec(TALLOC_CTX
*ctx
, const char *printername
, SEC_DESC_BUF
**secdesc_ctr
)
5061 if (strlen(printername
) > 2 && (temp
= strchr(printername
+ 2, '\\'))) {
5062 printername
= temp
+ 1;
5065 /* Fetch security descriptor from tdb */
5067 slprintf(key
, sizeof(key
)-1, "SECDESC/%s", printername
);
5069 if (tdb_prs_fetch(tdb_printers
, key
, &ps
, ctx
)!=0 ||
5070 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1)) {
5072 DEBUG(4,("using default secdesc for %s\n", printername
));
5074 if (!(*secdesc_ctr
= construct_default_printer_sdb(ctx
))) {
5078 /* Save default security descriptor for later */
5080 prs_init(&ps
, (uint32
)sec_desc_size((*secdesc_ctr
)->sec
) +
5081 sizeof(SEC_DESC_BUF
), ctx
, MARSHALL
);
5083 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1))
5084 tdb_prs_store(tdb_printers
, key
, &ps
);
5091 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5092 this security descriptor has been created when winbindd was
5093 down. Take ownership of security descriptor. */
5095 if (sid_equal((*secdesc_ctr
)->sec
->owner_sid
, &global_sid_World
)) {
5098 /* Change sd owner to workgroup administrator */
5100 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
5101 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
5102 SEC_DESC
*psd
= NULL
;
5107 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
5109 psd
= make_sec_desc(ctx
, (*secdesc_ctr
)->sec
->revision
, (*secdesc_ctr
)->sec
->type
,
5111 (*secdesc_ctr
)->sec
->grp_sid
,
5112 (*secdesc_ctr
)->sec
->sacl
,
5113 (*secdesc_ctr
)->sec
->dacl
,
5116 new_secdesc_ctr
= make_sec_desc_buf(ctx
, size
, psd
);
5118 /* Swap with other one */
5120 *secdesc_ctr
= new_secdesc_ctr
;
5124 nt_printing_setsec(printername
, *secdesc_ctr
);
5128 if (DEBUGLEVEL
>= 10) {
5129 SEC_ACL
*the_acl
= (*secdesc_ctr
)->sec
->dacl
;
5132 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5133 printername
, the_acl
->num_aces
));
5135 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5138 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5140 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str
,
5141 the_acl
->ace
[i
].type
, the_acl
->ace
[i
].flags
,
5142 the_acl
->ace
[i
].info
.mask
));
5152 1: level not implemented
5153 2: file doesn't exist
5154 3: can't allocate memory
5155 4: can't free memory
5156 5: non existant struct
5160 A printer and a printer driver are 2 different things.
5161 NT manages them separatelly, Samba does the same.
5162 Why ? Simply because it's easier and it makes sense !
5164 Now explanation: You have 3 printers behind your samba server,
5165 2 of them are the same make and model (laser A and B). But laser B
5166 has an 3000 sheet feeder and laser A doesn't such an option.
5167 Your third printer is an old dot-matrix model for the accounting :-).
5169 If the /usr/local/samba/lib directory (default dir), you will have
5170 5 files to describe all of this.
5172 3 files for the printers (1 by printer):
5175 NTprinter_accounting
5176 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5177 NTdriver_printer model X
5178 NTdriver_printer model Y
5180 jfm: I should use this comment for the text file to explain
5181 same thing for the forms BTW.
5182 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5186 /* Convert generic access rights to printer object specific access rights.
5187 It turns out that NT4 security descriptors use generic access rights and
5188 NT5 the object specific ones. */
5190 void map_printer_permissions(SEC_DESC
*sd
)
5194 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
5195 se_map_generic(&sd
->dacl
->ace
[i
].info
.mask
,
5196 &printer_generic_mapping
);
5200 /****************************************************************************
5201 Check a user has permissions to perform the given operation. We use the
5202 permission constants defined in include/rpc_spoolss.h to check the various
5203 actions we perform when checking printer access.
5205 PRINTER_ACCESS_ADMINISTER:
5206 print_queue_pause, print_queue_resume, update_printer_sec,
5207 update_printer, spoolss_addprinterex_level_2,
5208 _spoolss_setprinterdata
5213 JOB_ACCESS_ADMINISTER:
5214 print_job_delete, print_job_pause, print_job_resume,
5217 Try access control in the following order (for performance reasons):
5218 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5219 2) check security descriptor (bit comparisons in memory)
5220 3) "printer admins" (may result in numerous calls to winbind)
5222 ****************************************************************************/
5223 BOOL
print_access_check(struct current_user
*user
, int snum
, int access_type
)
5225 SEC_DESC_BUF
*secdesc
= NULL
;
5226 uint32 access_granted
;
5230 TALLOC_CTX
*mem_ctx
= NULL
;
5231 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5233 /* If user is NULL then use the current_user structure */
5236 user
= ¤t_user
;
5238 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5240 if ( user
->uid
== 0 || user_has_privileges(user
->nt_user_token
, &se_printop
) ) {
5244 /* Get printer name */
5246 pname
= PRINTERNAME(snum
);
5248 if (!pname
|| !*pname
) {
5253 /* Get printer security descriptor */
5255 if(!(mem_ctx
= talloc_init("print_access_check"))) {
5260 nt_printing_getsec(mem_ctx
, pname
, &secdesc
);
5262 if (access_type
== JOB_ACCESS_ADMINISTER
) {
5263 SEC_DESC_BUF
*parent_secdesc
= secdesc
;
5265 /* Create a child security descriptor to check permissions
5266 against. This is because print jobs are child objects
5267 objects of a printer. */
5269 secdesc
= se_create_child_secdesc(mem_ctx
, parent_secdesc
->sec
, False
);
5271 /* Now this is the bit that really confuses me. The access
5272 type needs to be changed from JOB_ACCESS_ADMINISTER to
5273 PRINTER_ACCESS_ADMINISTER for this to work. Something
5274 to do with the child (job) object becoming like a
5277 access_type
= PRINTER_ACCESS_ADMINISTER
;
5282 map_printer_permissions(secdesc
->sec
);
5284 result
= se_access_check(secdesc
->sec
, user
->nt_user_token
, access_type
,
5285 &access_granted
, &status
);
5287 DEBUG(4, ("access check was %s\n", result
? "SUCCESS" : "FAILURE"));
5289 /* see if we need to try the printer admin list */
5291 if ( access_granted
== 0 ) {
5292 if ( user_in_list(uidtoname(user
->uid
), lp_printer_admin(snum
), user
->groups
, user
->ngroups
) )
5296 talloc_destroy(mem_ctx
);
5304 /****************************************************************************
5305 Check the time parameters allow a print operation.
5306 *****************************************************************************/
5308 BOOL
print_time_access_check(int snum
)
5310 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5312 time_t now
= time(NULL
);
5316 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))))
5319 if (printer
->info_2
->starttime
== 0 && printer
->info_2
->untiltime
== 0)
5323 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
5325 if (mins
>= printer
->info_2
->starttime
&& mins
<= printer
->info_2
->untiltime
)
5328 free_a_printer(&printer
, 2);
5336 /****************************************************************************
5337 Fill in the servername sent in the _spoolss_open_printer_ex() call
5338 ****************************************************************************/
5339 char* get_server_name( Printer_entry
*printer
)
5341 return printer
->servername
;