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-2005.
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 3 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, see <http://www.gnu.org/licenses/>.
24 extern struct current_user current_user;
26 static TDB_CONTEXT *tdb_forms; /* used for forms files */
27 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
28 static TDB_CONTEXT *tdb_printers; /* used for printers files */
30 #define FORMS_PREFIX "FORMS/"
31 #define DRIVERS_PREFIX "DRIVERS/"
32 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
33 #define PRINTERS_PREFIX "PRINTERS/"
34 #define SECDESC_PREFIX "SECDESC/"
35 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
37 #define NTDRIVERS_DATABASE_VERSION_1 1
38 #define NTDRIVERS_DATABASE_VERSION_2 2
39 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
40 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
41 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
43 /* Map generic permissions to printer object specific permissions */
45 const struct generic_mapping printer_generic_mapping = {
52 const struct standard_mapping printer_std_mapping = {
59 /* Map generic permissions to print server object specific permissions */
61 const struct generic_mapping printserver_generic_mapping = {
68 const struct generic_mapping printserver_std_mapping = {
75 /* We need one default form to support our default printer. Msoft adds the
76 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
77 array index). Letter is always first, so (for the current code) additions
78 always put things in the correct order. */
79 static const nt_forms_struct default_forms[] = {
80 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
81 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
83 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
84 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
85 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
86 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
87 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
88 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
89 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
91 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
92 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
93 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
94 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
95 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
96 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
97 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
98 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
99 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
100 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
101 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
102 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
103 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
104 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
105 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
106 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
107 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
108 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
109 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
110 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
111 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
112 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
113 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
114 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
115 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
116 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
117 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
118 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
119 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
120 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
121 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
122 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
123 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
124 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
125 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
126 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
127 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
128 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
130 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
131 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
132 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
133 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
134 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
135 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
136 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
137 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
138 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
139 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
140 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
141 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
142 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
143 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
144 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
145 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
146 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
147 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
148 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
149 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
150 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
151 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
152 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
153 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
154 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
155 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
156 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
157 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
158 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
159 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
160 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
161 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
162 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
163 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
164 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
165 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
166 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
167 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
168 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
169 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
170 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
171 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
172 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
173 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
174 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
175 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
176 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
177 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
178 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
179 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
180 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
181 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
182 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
183 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
184 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
185 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
186 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
187 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
188 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
189 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
190 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
191 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
192 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
193 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
194 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
195 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
196 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
197 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
201 const char *long_archi;
202 const char *short_archi;
206 #define SPL_ARCH_WIN40 "WIN40"
207 #define SPL_ARCH_W32X86 "W32X86"
208 #define SPL_ARCH_W32MIPS "W32MIPS"
209 #define SPL_ARCH_W32ALPHA "W32ALPHA"
210 #define SPL_ARCH_W32PPC "W32PPC"
211 #define SPL_ARCH_IA64 "IA64"
212 #define SPL_ARCH_X64 "x64"
214 static const struct table_node archi_table[]= {
216 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
217 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
218 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
219 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
220 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
221 {"Windows IA64", SPL_ARCH_IA64, 3 },
222 {"Windows x64", SPL_ARCH_X64, 3 },
227 /****************************************************************************
228 generate a new TDB_DATA key for storing a printer
229 ****************************************************************************/
231 static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
237 fstrcpy(share, sharename);
240 keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
241 key = string_term_tdb_data(keystr ? keystr : "");
246 /****************************************************************************
247 generate a new TDB_DATA key for storing a printer security descriptor
248 ****************************************************************************/
250 static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
251 const char* sharename )
257 fstrcpy(share, sharename );
260 keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
261 key = string_term_tdb_data(keystr ? keystr : "");
266 /****************************************************************************
267 ****************************************************************************/
269 static bool upgrade_to_version_3(void)
271 TDB_DATA kbuf, newkey, dbuf;
273 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
275 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
276 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
278 dbuf = tdb_fetch(tdb_drivers, kbuf);
280 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
281 DEBUG(0,("upgrade_to_version_3:moving form\n"));
282 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
283 SAFE_FREE(dbuf.dptr);
284 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
287 if (tdb_delete(tdb_drivers, kbuf) != 0) {
288 SAFE_FREE(dbuf.dptr);
289 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
294 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
295 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
296 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
297 SAFE_FREE(dbuf.dptr);
298 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
301 if (tdb_delete(tdb_drivers, kbuf) != 0) {
302 SAFE_FREE(dbuf.dptr);
303 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
308 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
309 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
310 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
311 SAFE_FREE(dbuf.dptr);
312 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
315 if (tdb_delete(tdb_drivers, kbuf) != 0) {
316 SAFE_FREE(dbuf.dptr);
317 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
322 SAFE_FREE(dbuf.dptr);
328 /*******************************************************************
329 Fix an issue with security descriptors. Printer sec_desc must
330 use more than the generic bits that were previously used
331 in <= 3.0.14a. They must also have a owner and group SID assigned.
332 Otherwise, any printers than have been migrated to a Windows
333 host using printmig.exe will not be accessible.
334 *******************************************************************/
336 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
337 TDB_DATA data, void *state )
340 SEC_DESC_BUF *sd_orig = NULL;
341 SEC_DESC_BUF *sd_new, *sd_store;
342 SEC_DESC *sec, *new_sec;
343 TALLOC_CTX *ctx = state;
349 if (!data.dptr || data.dsize == 0) {
353 if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
357 /* upgrade the security descriptor */
361 prs_init( &ps, 0, ctx, UNMARSHALL );
362 prs_give_memory( &ps, (char *)data.dptr, data.dsize, False );
364 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
365 /* delete bad entries */
366 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
367 (const char *)key.dptr ));
368 tdb_delete( tdb_printers, key );
379 /* is this even valid? */
386 /* update access masks */
388 for ( i=0; i<sec->dacl->num_aces; i++ ) {
389 switch ( sec->dacl->aces[i].access_mask ) {
390 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
391 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
394 case GENERIC_ALL_ACCESS:
395 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
398 case READ_CONTROL_ACCESS:
399 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
401 default: /* no change */
406 /* create a new SEC_DESC with the appropriate owner and group SIDs */
408 string_to_sid(&sid, "S-1-5-32-544" );
409 new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
411 NULL, NULL, &size_new_sec );
416 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
422 if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
423 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
432 sd_size = ndr_size_security_descriptor(sd_store->sd, 0)
433 + sizeof(SEC_DESC_BUF);
434 prs_init(&ps, sd_size, ctx, MARSHALL);
436 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
437 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
442 data.dptr = (uint8 *)prs_data_p( &ps );
443 data.dsize = sd_size;
445 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
449 /* 0 to continue and non-zero to stop traversal */
451 return (result == -1);
454 /*******************************************************************
455 *******************************************************************/
457 static bool upgrade_to_version_4(void)
462 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
464 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
467 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
469 talloc_destroy( ctx );
471 return ( result != -1 );
474 /*******************************************************************
475 Fix an issue with security descriptors. Printer sec_desc must
476 use more than the generic bits that were previously used
477 in <= 3.0.14a. They must also have a owner and group SID assigned.
478 Otherwise, any printers than have been migrated to a Windows
479 host using printmig.exe will not be accessible.
480 *******************************************************************/
482 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
483 TDB_DATA data, void *state )
485 TALLOC_CTX *ctx = talloc_tos();
488 if (!data.dptr || data.dsize == 0)
491 /* upgrade printer records and security descriptors */
493 if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
494 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
496 else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
497 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
500 /* ignore this record */
504 /* delete the original record and store under the normalized key */
506 if ( tdb_delete( the_tdb, key ) != 0 ) {
507 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
512 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
513 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
521 /*******************************************************************
522 *******************************************************************/
524 static bool upgrade_to_version_5(void)
529 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
531 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
534 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
536 talloc_destroy( ctx );
538 return ( result != -1 );
541 /****************************************************************************
542 Open the NT printing tdbs. Done once before fork().
543 ****************************************************************************/
545 bool nt_printing_init(struct messaging_context *msg_ctx)
547 const char *vstring = "INFO/version";
551 if ( tdb_drivers && tdb_printers && tdb_forms )
555 tdb_close(tdb_drivers);
556 tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
558 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
559 state_path("ntdrivers.tdb"), strerror(errno) ));
564 tdb_close(tdb_printers);
565 tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
567 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
568 state_path("ntprinters.tdb"), strerror(errno) ));
573 tdb_close(tdb_forms);
574 tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
576 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
577 state_path("ntforms.tdb"), strerror(errno) ));
581 /* handle a Samba upgrade */
583 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
585 DEBUG(10, ("Fresh database\n"));
586 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
587 vers_id = NTDRIVERS_DATABASE_VERSION_5;
590 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
592 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
593 if (!upgrade_to_version_3())
595 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
596 vers_id = NTDRIVERS_DATABASE_VERSION_3;
599 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
600 /* Written on a bigendian machine with old fetch_int code. Save as le. */
601 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
602 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
603 vers_id = NTDRIVERS_DATABASE_VERSION_3;
606 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
607 if ( !upgrade_to_version_4() )
609 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
610 vers_id = NTDRIVERS_DATABASE_VERSION_4;
613 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
614 if ( !upgrade_to_version_5() )
616 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
617 vers_id = NTDRIVERS_DATABASE_VERSION_5;
621 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
622 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
627 update_c_setprinter(True);
630 * register callback to handle updating printers as new
631 * drivers are installed
634 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
635 do_drv_upgrade_printer);
638 * register callback to handle updating printer data
639 * when a driver is initialized
642 messaging_register(msg_ctx, NULL, MSG_PRINTERDATA_INIT_RESET,
643 reset_all_printerdata);
645 /* of course, none of the message callbacks matter if you don't
646 tell messages.c that you interested in receiving PRINT_GENERAL
647 msgs. This is done in claim_connection() */
650 if ( lp_security() == SEC_ADS ) {
651 win_rc = check_published_printers();
652 if (!W_ERROR_IS_OK(win_rc))
653 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
659 /*******************************************************************
660 Function to allow filename parsing "the old way".
661 ********************************************************************/
663 static char *driver_unix_convert(connection_struct *conn,
664 const char *old_name,
665 SMB_STRUCT_STAT *pst)
667 TALLOC_CTX *ctx = talloc_tos();
668 char *name = talloc_strdup(ctx, old_name);
669 char *new_name = NULL;
675 name = unix_clean_name(ctx, name);
679 trim_string(name,"/","/");
680 unix_convert(ctx,conn, name, false, &new_name, NULL, pst);
684 /*******************************************************************
685 tdb traversal function for counting printers.
686 ********************************************************************/
688 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
689 TDB_DATA data, void *context)
691 int *printer_count = (int*)context;
693 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
695 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
701 /*******************************************************************
702 Update the spooler global c_setprinter. This variable is initialized
703 when the parent smbd starts with the number of existing printers. It
704 is monotonically increased by the current number of printers *after*
705 each add or delete printer RPC. Only Microsoft knows why... JRR020119
706 ********************************************************************/
708 uint32 update_c_setprinter(bool initialize)
711 int32 printer_count = 0;
713 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
715 /* Traverse the tdb, counting the printers */
716 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
718 /* If initializing, set c_setprinter to current printers count
719 * otherwise, bump it by the current printer count
722 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
724 c_setprinter = printer_count;
726 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
727 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
729 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
731 return (uint32)c_setprinter;
734 /*******************************************************************
735 Get the spooler global c_setprinter, accounting for initialization.
736 ********************************************************************/
738 uint32 get_c_setprinter(void)
740 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
742 if (c_setprinter == (int32)-1)
743 c_setprinter = update_c_setprinter(True);
745 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
747 return (uint32)c_setprinter;
750 /****************************************************************************
751 Get builtin form struct list.
752 ****************************************************************************/
754 int get_builtin_ntforms(nt_forms_struct **list)
756 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
760 return sizeof(default_forms) / sizeof(default_forms[0]);
763 /****************************************************************************
764 get a builtin form struct
765 ****************************************************************************/
767 bool get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
771 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
772 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
773 count = sizeof(default_forms) / sizeof(default_forms[0]);
774 for (i=0;i<count;i++) {
775 if (strequal(form_name,default_forms[i].name)) {
776 DEBUGADD(6,("Found builtin form %s \n", form_name));
777 memcpy(form,&default_forms[i],sizeof(*form));
785 /****************************************************************************
786 get a form struct list.
787 ****************************************************************************/
789 int get_ntforms(nt_forms_struct **list)
791 TDB_DATA kbuf, newkey, dbuf;
792 nt_forms_struct form;
799 for (kbuf = tdb_firstkey(tdb_forms);
801 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
803 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
806 dbuf = tdb_fetch(tdb_forms, kbuf);
810 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
811 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
812 &i, &form.flag, &form.width, &form.length, &form.left,
813 &form.top, &form.right, &form.bottom);
814 SAFE_FREE(dbuf.dptr);
815 if (ret != dbuf.dsize)
818 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
820 DEBUG(0,("get_ntforms: Realloc fail.\n"));
831 /****************************************************************************
832 write a form struct list
833 ****************************************************************************/
835 int write_ntforms(nt_forms_struct **list, int number)
837 TALLOC_CTX *ctx = talloc_tos();
844 for (i=0;i<number;i++) {
845 /* save index, so list is rebuilt in correct order */
846 len = tdb_pack(NULL, 0, "dddddddd",
847 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
848 (*list)[i].left, (*list)[i].top, (*list)[i].right,
853 buf = TALLOC_ARRAY(ctx, char, len);
857 len = tdb_pack((uint8 *)buf, len, "dddddddd",
858 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
859 (*list)[i].left, (*list)[i].top, (*list)[i].right,
861 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
866 dbuf.dptr = (uint8 *)buf;
867 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
879 /****************************************************************************
880 add a form struct at the end of the list
881 ****************************************************************************/
882 bool add_a_form(nt_forms_struct **list, const FORM *form, int *count)
889 * NT tries to add forms even when
890 * they are already in the base
891 * only update the values if already present
896 unistr2_to_ascii(form_name, &form->name, sizeof(form_name));
897 for (n=0; n<*count; n++) {
898 if ( strequal((*list)[n].name, form_name) ) {
905 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
906 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
909 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name));
913 (*list)[n].flag=form->flags;
914 (*list)[n].width=form->size_x;
915 (*list)[n].length=form->size_y;
916 (*list)[n].left=form->left;
917 (*list)[n].top=form->top;
918 (*list)[n].right=form->right;
919 (*list)[n].bottom=form->bottom;
921 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
922 update ? "updated" : "added", form_name));
927 /****************************************************************************
928 Delete a named form struct.
929 ****************************************************************************/
931 bool delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
939 unistr2_to_ascii(form_name, del_name, sizeof(form_name));
941 for (n=0; n<*count; n++) {
942 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
943 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
949 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
950 *ret = WERR_INVALID_PARAM;
954 if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
958 if (tdb_delete_bystring(tdb_forms, key) != 0) {
967 /****************************************************************************
968 Update a form struct.
969 ****************************************************************************/
971 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
975 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name));
977 DEBUG(106, ("[%s]\n", form_name));
978 for (n=0; n<count; n++) {
979 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
980 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
984 if (n==count) return;
986 (*list)[n].flag=form->flags;
987 (*list)[n].width=form->size_x;
988 (*list)[n].length=form->size_y;
989 (*list)[n].left=form->left;
990 (*list)[n].top=form->top;
991 (*list)[n].right=form->right;
992 (*list)[n].bottom=form->bottom;
995 /****************************************************************************
996 Get the nt drivers list.
997 Traverse the database and look-up the matching names.
998 ****************************************************************************/
999 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
1002 const char *short_archi;
1004 TDB_DATA kbuf, newkey;
1006 short_archi = get_short_archi(architecture);
1011 if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
1012 short_archi, version) < 0) {
1016 for (kbuf = tdb_firstkey(tdb_drivers);
1018 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
1020 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
1023 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
1024 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
1029 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
1037 /****************************************************************************
1038 Function to do the mapping between the long architecture name and
1040 ****************************************************************************/
1042 const char *get_short_archi(const char *long_archi)
1046 DEBUG(107,("Getting architecture dependant directory\n"));
1049 } while ( (archi_table[i].long_archi!=NULL ) &&
1050 StrCaseCmp(long_archi, archi_table[i].long_archi) );
1052 if (archi_table[i].long_archi==NULL) {
1053 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1057 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1059 DEBUGADD(108,("index: [%d]\n", i));
1060 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1061 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1063 return archi_table[i].short_archi;
1066 /****************************************************************************
1067 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1068 There are two case to be covered here: PE (Portable Executable) and NE (New
1069 Executable) files. Both files support the same INFO structure, but PE files
1070 store the signature in unicode, and NE files store it as !unicode.
1071 returns -1 on error, 1 on version info found, and 0 on no version info found.
1072 ****************************************************************************/
1074 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1080 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1081 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1082 fname, DOS_HEADER_SIZE));
1086 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1087 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1088 fname, (unsigned long)byte_count));
1089 goto no_version_info;
1092 /* Is this really a DOS header? */
1093 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1094 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1095 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1096 goto no_version_info;
1099 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1100 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1101 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1103 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1104 goto no_version_info;
1107 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1108 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1109 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1110 fname, (unsigned long)byte_count));
1111 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1112 goto no_version_info;
1115 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1116 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1117 unsigned int num_sections;
1118 unsigned int section_table_bytes;
1120 /* Just skip over optional header to get to section table */
1121 if (SMB_VFS_LSEEK(fsp,
1122 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1123 SEEK_CUR) == (SMB_OFF_T)-1) {
1124 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1129 /* get the section table */
1130 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1131 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1132 if (section_table_bytes == 0)
1136 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1137 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1138 fname, section_table_bytes));
1142 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1143 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1144 fname, (unsigned long)byte_count));
1148 /* Iterate the section table looking for the resource section ".rsrc" */
1149 for (i = 0; i < num_sections; i++) {
1150 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1152 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1153 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1154 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1156 if (section_bytes == 0)
1160 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1161 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1162 fname, section_bytes));
1166 /* Seek to the start of the .rsrc section info */
1167 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1168 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1173 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1174 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1175 fname, (unsigned long)byte_count));
1179 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1182 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1183 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1184 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1185 /* Align to next long address */
1186 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1188 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1189 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1190 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1192 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1193 fname, *major, *minor,
1194 (*major>>16)&0xffff, *major&0xffff,
1195 (*minor>>16)&0xffff, *minor&0xffff));
1204 /* Version info not found, fall back to origin date/time */
1205 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1209 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1210 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1211 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1212 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1213 /* At this point, we assume the file is in error. It still could be somthing
1214 * else besides a NE file, but it unlikely at this point. */
1218 /* Allocate a bit more space to speed up things */
1220 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1221 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1222 fname, PE_HEADER_SIZE));
1226 /* This is a HACK! I got tired of trying to sort through the messy
1227 * 'NE' file format. If anyone wants to clean this up please have at
1228 * it, but this works. 'NE' files will eventually fade away. JRR */
1229 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1230 /* Cover case that should not occur in a well formed 'NE' .dll file */
1231 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1233 for(i=0; i<byte_count; i++) {
1234 /* Fast skip past data that can't possibly match */
1235 if (buf[i] != 'V') continue;
1237 /* Potential match data crosses buf boundry, move it to beginning
1238 * of buf, and fill the buf with as much as it will hold. */
1239 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1242 memcpy(buf, &buf[i], byte_count-i);
1243 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1244 (byte_count-i))) < 0) {
1246 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1251 byte_count = bc + (byte_count - i);
1252 if (byte_count<VS_VERSION_INFO_SIZE) break;
1257 /* Check that the full signature string and the magic number that
1258 * follows exist (not a perfect solution, but the chances that this
1259 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1260 * twice, as it is simpler to read the code. */
1261 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1262 /* Compute skip alignment to next long address */
1263 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1264 sizeof(VS_SIGNATURE)) & 3;
1265 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1267 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1268 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1269 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1270 fname, *major, *minor,
1271 (*major>>16)&0xffff, *major&0xffff,
1272 (*minor>>16)&0xffff, *minor&0xffff));
1279 /* Version info not found, fall back to origin date/time */
1280 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1285 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1286 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1287 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1298 /****************************************************************************
1299 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1300 share one or more files. During the MS installation process files are checked
1301 to insure that only a newer version of a shared file is installed over an
1302 older version. There are several possibilities for this comparison. If there
1303 is no previous version, the new one is newer (obviously). If either file is
1304 missing the version info structure, compare the creation date (on Unix use
1305 the modification date). Otherwise chose the numerically larger version number.
1306 ****************************************************************************/
1308 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1310 bool use_version = true;
1311 char *filepath = NULL;
1315 time_t new_create_time;
1319 time_t old_create_time;
1321 files_struct *fsp = NULL;
1323 SMB_STRUCT_STAT stat_buf;
1327 SET_STAT_INVALID(st);
1328 SET_STAT_INVALID(stat_buf);
1329 new_create_time = (time_t)0;
1330 old_create_time = (time_t)0;
1332 /* Get file version info (if available) for previous file (if it exists) */
1333 filepath = driver_unix_convert(conn,old_file,&stat_buf);
1338 status = open_file_ntcreate(conn, NULL, filepath, &stat_buf,
1340 FILE_SHARE_READ|FILE_SHARE_WRITE,
1343 FILE_ATTRIBUTE_NORMAL,
1347 if (!NT_STATUS_IS_OK(status)) {
1348 /* Old file not found, so by definition new file is in fact newer */
1349 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1354 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1360 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1362 use_version = false;
1363 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1366 old_create_time = st.st_mtime;
1367 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1370 close_file(fsp, NORMAL_CLOSE);
1372 /* Get file version info (if available) for new file */
1373 filepath = driver_unix_convert(conn,new_file,&stat_buf);
1378 status = open_file_ntcreate(conn, NULL, filepath, &stat_buf,
1380 FILE_SHARE_READ|FILE_SHARE_WRITE,
1383 FILE_ATTRIBUTE_NORMAL,
1387 if (!NT_STATUS_IS_OK(status)) {
1388 /* New file not found, this shouldn't occur if the caller did its job */
1389 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1394 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1400 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1402 use_version = false;
1403 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1406 new_create_time = st.st_mtime;
1407 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1410 close_file(fsp, NORMAL_CLOSE);
1412 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1413 /* Compare versions and choose the larger version number */
1414 if (new_major > old_major ||
1415 (new_major == old_major && new_minor > old_minor)) {
1417 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1421 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1426 /* Compare modification time/dates and choose the newest time/date */
1427 if (new_create_time > old_create_time) {
1428 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1432 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1439 close_file(fsp, NORMAL_CLOSE);
1443 /****************************************************************************
1444 Determine the correct cVersion associated with an architecture and driver
1445 ****************************************************************************/
1446 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1447 struct current_user *user, WERROR *perr)
1451 char *driverpath = NULL;
1454 files_struct *fsp = NULL;
1456 connection_struct *conn;
1459 SET_STAT_INVALID(st);
1461 *perr = WERR_INVALID_PARAM;
1463 /* If architecture is Windows 95/98/ME, the version is always 0. */
1464 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1465 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1470 /* If architecture is Windows x64, the version is always 3. */
1471 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1472 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1478 * Connect to the print$ share under the same account as the user connected
1479 * to the rpc pipe. Note we must still be root to do this.
1482 /* Null password is ok - we are already an authenticated user... */
1483 null_pw = data_blob_null;
1484 fstrcpy(res_type, "A:");
1486 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1490 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1491 *perr = ntstatus_to_werror(nt_status);
1495 /* We are temporarily becoming the connection user. */
1496 if (!become_user(conn, user->vuid)) {
1497 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1498 *perr = WERR_ACCESS_DENIED;
1502 /* Open the driver file (Portable Executable format) and determine the
1503 * deriver the cversion. */
1504 driverpath = talloc_asprintf(talloc_tos(),
1513 driverpath = driver_unix_convert(conn,driverpath,&st);
1519 if (!vfs_file_exist(conn, driverpath, &st)) {
1520 *perr = WERR_BADFILE;
1524 status = open_file_ntcreate(conn, NULL, driverpath, &st,
1526 FILE_SHARE_READ|FILE_SHARE_WRITE,
1529 FILE_ATTRIBUTE_NORMAL,
1533 if (!NT_STATUS_IS_OK(status)) {
1534 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1535 driverpath, errno));
1536 *perr = WERR_ACCESS_DENIED;
1541 int ret = get_file_version(fsp, driverpath, &major, &minor);
1542 if (ret == -1) goto error_exit;
1545 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1550 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1551 * for more details. Version in this case is not just the version of the
1552 * file, but the version in the sense of kernal mode (2) vs. user mode
1553 * (3) drivers. Other bits of the version fields are the version info.
1556 cversion = major & 0x0000ffff;
1558 case 2: /* WinNT drivers */
1559 case 3: /* Win2K drivers */
1563 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1564 driverpath, cversion));
1568 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1569 driverpath, major, minor));
1572 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1573 driverpath, cversion));
1575 close_file(fsp, NORMAL_CLOSE);
1576 close_cnum(conn, user->vuid);
1585 close_file(fsp, NORMAL_CLOSE);
1587 close_cnum(conn, user->vuid);
1592 /****************************************************************************
1593 ****************************************************************************/
1594 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1595 struct current_user *user)
1597 const char *architecture;
1603 /* clean up the driver name.
1604 * we can get .\driver.dll
1605 * or worse c:\windows\system\driver.dll !
1607 /* using an intermediate string to not have overlaping memcpy()'s */
1608 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1609 fstrcpy(new_name, p+1);
1610 fstrcpy(driver->driverpath, new_name);
1613 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1614 fstrcpy(new_name, p+1);
1615 fstrcpy(driver->datafile, new_name);
1618 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1619 fstrcpy(new_name, p+1);
1620 fstrcpy(driver->configfile, new_name);
1623 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1624 fstrcpy(new_name, p+1);
1625 fstrcpy(driver->helpfile, new_name);
1628 if (driver->dependentfiles) {
1629 for (i=0; *driver->dependentfiles[i]; i++) {
1630 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1631 fstrcpy(new_name, p+1);
1632 fstrcpy(driver->dependentfiles[i], new_name);
1637 architecture = get_short_archi(driver->environment);
1638 if (!architecture) {
1639 return WERR_UNKNOWN_PRINTER_DRIVER;
1642 /* jfm:7/16/2000 the client always sends the cversion=0.
1643 * The server should check which version the driver is by reading
1644 * the PE header of driver->driverpath.
1646 * For Windows 95/98 the version is 0 (so the value sent is correct)
1647 * For Windows NT (the architecture doesn't matter)
1648 * NT 3.1: cversion=0
1649 * NT 3.5/3.51: cversion=1
1653 if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1659 /****************************************************************************
1660 ****************************************************************************/
1661 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1663 const char *architecture;
1669 /* clean up the driver name.
1670 * we can get .\driver.dll
1671 * or worse c:\windows\system\driver.dll !
1673 /* using an intermediate string to not have overlaping memcpy()'s */
1674 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1675 fstrcpy(new_name, p+1);
1676 fstrcpy(driver->driverpath, new_name);
1679 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1680 fstrcpy(new_name, p+1);
1681 fstrcpy(driver->datafile, new_name);
1684 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1685 fstrcpy(new_name, p+1);
1686 fstrcpy(driver->configfile, new_name);
1689 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1690 fstrcpy(new_name, p+1);
1691 fstrcpy(driver->helpfile, new_name);
1694 if (driver->dependentfiles) {
1695 for (i=0; *driver->dependentfiles[i]; i++) {
1696 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1697 fstrcpy(new_name, p+1);
1698 fstrcpy(driver->dependentfiles[i], new_name);
1703 architecture = get_short_archi(driver->environment);
1704 if (!architecture) {
1705 return WERR_UNKNOWN_PRINTER_DRIVER;
1708 /* jfm:7/16/2000 the client always sends the cversion=0.
1709 * The server should check which version the driver is by reading
1710 * the PE header of driver->driverpath.
1712 * For Windows 95/98 the version is 0 (so the value sent is correct)
1713 * For Windows NT (the architecture doesn't matter)
1714 * NT 3.1: cversion=0
1715 * NT 3.5/3.51: cversion=1
1720 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1726 /****************************************************************************
1727 ****************************************************************************/
1728 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1729 uint32 level, struct current_user *user)
1734 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1735 driver=driver_abstract.info_3;
1736 return clean_up_driver_struct_level_3(driver, user);
1740 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1741 driver=driver_abstract.info_6;
1742 return clean_up_driver_struct_level_6(driver, user);
1745 return WERR_INVALID_PARAM;
1749 /****************************************************************************
1750 This function sucks and should be replaced. JRA.
1751 ****************************************************************************/
1753 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1755 dst->cversion = src->version;
1757 fstrcpy( dst->name, src->name);
1758 fstrcpy( dst->environment, src->environment);
1759 fstrcpy( dst->driverpath, src->driverpath);
1760 fstrcpy( dst->datafile, src->datafile);
1761 fstrcpy( dst->configfile, src->configfile);
1762 fstrcpy( dst->helpfile, src->helpfile);
1763 fstrcpy( dst->monitorname, src->monitorname);
1764 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1765 dst->dependentfiles = src->dependentfiles;
1768 #if 0 /* Debugging function */
1770 static char* ffmt(unsigned char *c){
1772 static char ffmt_str[17];
1774 for (i=0; i<16; i++) {
1775 if ((c[i] < ' ') || (c[i] > '~'))
1786 /****************************************************************************
1787 ****************************************************************************/
1788 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1789 struct current_user *user, WERROR *perr)
1791 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1792 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1793 const char *architecture;
1794 char *new_dir = NULL;
1795 char *old_name = NULL;
1796 char *new_name = NULL;
1798 connection_struct *conn;
1803 TALLOC_CTX *ctx = talloc_tos();
1809 driver=driver_abstract.info_3;
1810 else if (level==6) {
1811 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1812 driver = &converted_driver;
1814 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1815 return WERR_UNKNOWN_LEVEL;
1818 architecture = get_short_archi(driver->environment);
1819 if (!architecture) {
1820 return WERR_UNKNOWN_PRINTER_DRIVER;
1824 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1825 * Note we must be root to do this.
1828 null_pw = data_blob_null;
1829 fstrcpy(res_type, "A:");
1831 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1835 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1836 *perr = ntstatus_to_werror(nt_status);
1837 return WERR_NO_SUCH_SHARE;
1841 * Save who we are - we are temporarily becoming the connection user.
1844 if (!become_user(conn, conn->vuid)) {
1845 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1846 return WERR_ACCESS_DENIED;
1849 /* WE ARE NOW RUNNING AS USER conn->vuid !!!!! */
1852 * make the directories version and version\driver_name
1853 * under the architecture directory.
1855 DEBUG(5,("Creating first directory\n"));
1856 new_dir = talloc_asprintf(ctx,
1864 new_dir = driver_unix_convert(conn,new_dir,&st);
1870 create_directory(conn, NULL, new_dir);
1872 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1873 * listed for this driver which has already been moved, skip it (note:
1874 * drivers may list the same file name several times. Then check if the
1875 * file already exists in archi\cversion\, if so, check that the version
1876 * info (or time stamps if version info is unavailable) is newer (or the
1877 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1878 * Otherwise, delete the file.
1880 * If a file is not moved to archi\cversion\ because of an error, all the
1881 * rest of the 'unmoved' driver files are removed from archi\. If one or
1882 * more of the driver's files was already moved to archi\cversion\, it
1883 * potentially leaves the driver in a partially updated state. Version
1884 * trauma will most likely occur if an client attempts to use any printer
1885 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1886 * done is appropriate... later JRR
1889 DEBUG(5,("Moving files now !\n"));
1891 if (driver->driverpath && strlen(driver->driverpath)) {
1892 new_name = talloc_asprintf(ctx,
1895 driver->driverpath);
1900 old_name = talloc_asprintf(ctx,
1903 driver->driverpath);
1909 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1910 new_name = driver_unix_convert(conn,new_name,&st);
1915 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1916 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1917 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1918 new_name, old_name));
1919 *perr = WERR_ACCESS_DENIED;
1925 if (driver->datafile && strlen(driver->datafile)) {
1926 if (!strequal(driver->datafile, driver->driverpath)) {
1927 new_name = talloc_asprintf(ctx,
1935 old_name = talloc_asprintf(ctx,
1943 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1944 new_name = driver_unix_convert(conn,new_name,&st);
1949 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1950 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1951 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1952 new_name, old_name));
1953 *perr = WERR_ACCESS_DENIED;
1960 if (driver->configfile && strlen(driver->configfile)) {
1961 if (!strequal(driver->configfile, driver->driverpath) &&
1962 !strequal(driver->configfile, driver->datafile)) {
1963 new_name = talloc_asprintf(ctx,
1966 driver->configfile);
1971 old_name = talloc_asprintf(ctx,
1974 driver->configfile);
1979 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1980 new_name = driver_unix_convert(conn,new_name,&st);
1985 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1986 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1987 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1988 new_name, old_name));
1989 *perr = WERR_ACCESS_DENIED;
1996 if (driver->helpfile && strlen(driver->helpfile)) {
1997 if (!strequal(driver->helpfile, driver->driverpath) &&
1998 !strequal(driver->helpfile, driver->datafile) &&
1999 !strequal(driver->helpfile, driver->configfile)) {
2000 new_name = talloc_asprintf(ctx,
2008 old_name = talloc_asprintf(ctx,
2016 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
2017 new_name = driver_unix_convert(conn,new_name,&st);
2022 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
2023 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
2024 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
2025 new_name, old_name));
2026 *perr = WERR_ACCESS_DENIED;
2033 if (driver->dependentfiles) {
2034 for (i=0; *driver->dependentfiles[i]; i++) {
2035 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
2036 !strequal(driver->dependentfiles[i], driver->datafile) &&
2037 !strequal(driver->dependentfiles[i], driver->configfile) &&
2038 !strequal(driver->dependentfiles[i], driver->helpfile)) {
2040 for (j=0; j < i; j++) {
2041 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
2046 new_name = talloc_asprintf(ctx,
2049 driver->dependentfiles[i]);
2054 old_name = talloc_asprintf(ctx,
2057 driver->dependentfiles[i]);
2062 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
2063 new_name = driver_unix_convert(conn,new_name,&st);
2068 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name,
2069 OPENX_FILE_EXISTS_TRUNCATE|
2070 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
2071 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
2072 new_name, old_name));
2073 *perr = WERR_ACCESS_DENIED;
2084 close_cnum(conn, user->vuid);
2087 if (W_ERROR_EQUAL(*perr, WERR_OK)) {
2091 return WERR_UNKNOWN_PRINTER_DRIVER;
2096 /****************************************************************************
2097 ****************************************************************************/
2099 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
2101 TALLOC_CTX *ctx = talloc_tos();
2103 const char *architecture;
2104 char *directory = NULL;
2111 architecture = get_short_archi(driver->environment);
2112 if (!architecture) {
2116 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2117 * \\server is added in the rpc server layer.
2118 * It does make sense to NOT store the server's name in the printer TDB.
2121 directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
2122 architecture, driver->cversion);
2127 /* .inf files do not always list a file for each of the four standard files.
2128 * Don't prepend a path to a null filename, or client claims:
2129 * "The server on which the printer resides does not have a suitable
2130 * <printer driver name> printer driver installed. Click OK if you
2131 * wish to install the driver on your local machine."
2133 if (strlen(driver->driverpath)) {
2134 fstrcpy(temp_name, driver->driverpath);
2135 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
2138 if (strlen(driver->datafile)) {
2139 fstrcpy(temp_name, driver->datafile);
2140 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
2143 if (strlen(driver->configfile)) {
2144 fstrcpy(temp_name, driver->configfile);
2145 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
2148 if (strlen(driver->helpfile)) {
2149 fstrcpy(temp_name, driver->helpfile);
2150 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
2153 if (driver->dependentfiles) {
2154 for (i=0; *driver->dependentfiles[i]; i++) {
2155 fstrcpy(temp_name, driver->dependentfiles[i]);
2156 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
2160 key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
2161 architecture, driver->cversion, driver->name);
2166 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
2173 len += tdb_pack(buf+len, buflen-len, "dffffffff",
2176 driver->environment,
2181 driver->monitorname,
2182 driver->defaultdatatype);
2184 if (driver->dependentfiles) {
2185 for (i=0; *driver->dependentfiles[i]; i++) {
2186 len += tdb_pack(buf+len, buflen-len, "f",
2187 driver->dependentfiles[i]);
2191 if (len != buflen) {
2192 buf = (uint8 *)SMB_REALLOC(buf, len);
2194 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2205 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2209 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2215 /****************************************************************************
2216 ****************************************************************************/
2217 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2219 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2222 info3.cversion = driver->version;
2223 fstrcpy(info3.name,driver->name);
2224 fstrcpy(info3.environment,driver->environment);
2225 fstrcpy(info3.driverpath,driver->driverpath);
2226 fstrcpy(info3.datafile,driver->datafile);
2227 fstrcpy(info3.configfile,driver->configfile);
2228 fstrcpy(info3.helpfile,driver->helpfile);
2229 fstrcpy(info3.monitorname,driver->monitorname);
2230 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2231 info3.dependentfiles = driver->dependentfiles;
2233 return add_a_printer_driver_3(&info3);
2237 /****************************************************************************
2238 ****************************************************************************/
2239 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2241 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2245 fstrcpy(info.name, driver);
2246 fstrcpy(info.defaultdatatype, "RAW");
2248 fstrcpy(info.driverpath, "");
2249 fstrcpy(info.datafile, "");
2250 fstrcpy(info.configfile, "");
2251 fstrcpy(info.helpfile, "");
2253 if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2256 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2257 fstrcpy(info.dependentfiles[0], "");
2259 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
2261 SAFE_FREE(info.dependentfiles);
2268 /****************************************************************************
2269 ****************************************************************************/
2270 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
2272 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2274 const char *architecture;
2279 ZERO_STRUCT(driver);
2281 architecture = get_short_archi(arch);
2282 if ( !architecture ) {
2283 return WERR_UNKNOWN_PRINTER_DRIVER;
2286 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2288 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2291 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2293 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
2294 architecture, version, drivername) < 0) {
2298 dbuf = tdb_fetch_bystring(tdb_drivers, key);
2301 return WERR_UNKNOWN_PRINTER_DRIVER;
2304 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2313 driver.defaultdatatype);
2316 while (len < dbuf.dsize) {
2317 driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2318 if ( !driver.dependentfiles ) {
2319 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2323 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2324 &driver.dependentfiles[i]);
2328 if ( driver.dependentfiles )
2329 fstrcpy( driver.dependentfiles[i], "" );
2331 SAFE_FREE(dbuf.dptr);
2334 if (len != dbuf.dsize) {
2335 SAFE_FREE(driver.dependentfiles);
2337 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2340 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2342 SAFE_FREE(driver.dependentfiles);
2349 /****************************************************************************
2350 Debugging function, dump at level 6 the struct in the logs.
2351 ****************************************************************************/
2353 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2356 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2359 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2365 if (driver.info_3 == NULL)
2368 info3=driver.info_3;
2370 DEBUGADD(20,("version:[%d]\n", info3->cversion));
2371 DEBUGADD(20,("name:[%s]\n", info3->name));
2372 DEBUGADD(20,("environment:[%s]\n", info3->environment));
2373 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
2374 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
2375 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
2376 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
2377 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
2378 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2380 for (i=0; info3->dependentfiles &&
2381 *info3->dependentfiles[i]; i++) {
2382 DEBUGADD(20,("dependentfile:[%s]\n",
2383 info3->dependentfiles[i]));
2390 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2398 /****************************************************************************
2399 ****************************************************************************/
2400 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2404 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2409 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2410 nt_devmode->devicename,
2411 nt_devmode->formname,
2413 nt_devmode->specversion,
2414 nt_devmode->driverversion,
2416 nt_devmode->driverextra,
2417 nt_devmode->orientation,
2418 nt_devmode->papersize,
2419 nt_devmode->paperlength,
2420 nt_devmode->paperwidth,
2423 nt_devmode->defaultsource,
2424 nt_devmode->printquality,
2427 nt_devmode->yresolution,
2428 nt_devmode->ttoption,
2429 nt_devmode->collate,
2430 nt_devmode->logpixels,
2433 nt_devmode->bitsperpel,
2434 nt_devmode->pelswidth,
2435 nt_devmode->pelsheight,
2436 nt_devmode->displayflags,
2437 nt_devmode->displayfrequency,
2438 nt_devmode->icmmethod,
2439 nt_devmode->icmintent,
2440 nt_devmode->mediatype,
2441 nt_devmode->dithertype,
2442 nt_devmode->reserved1,
2443 nt_devmode->reserved2,
2444 nt_devmode->panningwidth,
2445 nt_devmode->panningheight,
2446 nt_devmode->nt_dev_private);
2448 if (nt_devmode->nt_dev_private) {
2449 len += tdb_pack(buf+len, buflen-len, "B",
2450 nt_devmode->driverextra,
2451 nt_devmode->nt_dev_private);
2454 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2459 /****************************************************************************
2460 Pack all values in all printer keys
2461 ***************************************************************************/
2463 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2467 REGISTRY_VALUE *val;
2468 REGVAL_CTR *val_ctr;
2475 /* loop over all keys */
2477 for ( i=0; i<data->num_keys; i++ ) {
2478 val_ctr = data->keys[i].values;
2479 num_values = regval_ctr_numvals( val_ctr );
2481 /* pack the keyname followed by a empty value */
2483 len += tdb_pack(buf+len, buflen-len, "pPdB",
2484 &data->keys[i].name,
2490 /* now loop over all values */
2492 for ( j=0; j<num_values; j++ ) {
2493 /* pathname should be stored as <key>\<value> */
2495 val = regval_ctr_specific_value( val_ctr, j );
2496 if (asprintf(&path, "%s\\%s",
2498 regval_name(val)) < 0) {
2502 len += tdb_pack(buf+len, buflen-len, "pPdB",
2507 regval_data_p(val) );
2509 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2517 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2523 /****************************************************************************
2524 Delete a printer - this just deletes the printer info file, any open
2525 handles are not affected.
2526 ****************************************************************************/
2528 uint32 del_a_printer(const char *sharename)
2531 char *printdb_path = NULL;
2532 TALLOC_CTX *ctx = talloc_tos();
2534 kbuf = make_printer_tdbkey(ctx, sharename);
2535 tdb_delete(tdb_printers, kbuf);
2537 kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2538 tdb_delete(tdb_printers, kbuf);
2540 close_all_print_db();
2542 if (geteuid() == 0) {
2543 if (asprintf(&printdb_path, "%s%s.tdb",
2544 lock_path("printing/"),
2548 unlink(printdb_path);
2549 SAFE_FREE(printdb_path);
2555 /****************************************************************************
2556 ****************************************************************************/
2557 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2563 TDB_DATA kbuf, dbuf;
2566 * in addprinter: no servername and the printer is the name
2567 * in setprinter: servername is \\server
2568 * and printer is \\server\\printer
2570 * Samba manages only local printers.
2571 * we currently don't support things like i
2572 * path=\\other_server\printer
2574 * We only store the printername, not \\server\printername
2577 if ( info->servername[0] != '\0' ) {
2578 trim_string(info->printername, info->servername, NULL);
2579 trim_char(info->printername, '\\', '\0');
2580 info->servername[0]='\0';
2584 * JFM: one day I'll forget.
2585 * below that's info->portname because that's the SAMBA sharename
2586 * and I made NT 'thinks' it's the portname
2587 * the info->sharename is the thing you can name when you add a printer
2588 * that's the short-name when you create shared printer for 95/98
2589 * So I've made a limitation in SAMBA: you can only have 1 printer model
2590 * behind a SAMBA share.
2598 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2601 info->default_priority,
2618 info->printprocessor,
2622 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2623 retlen = pack_values( info->data, buf+len, buflen-len );
2630 if (buflen != len) {
2631 buf = (uint8 *)SMB_REALLOC(buf, len);
2633 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2641 kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2646 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2649 if (!W_ERROR_IS_OK(ret))
2650 DEBUG(8, ("error updating printer to tdb on disk\n"));
2654 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2655 info->sharename, info->drivername, info->portname, len));
2661 /****************************************************************************
2662 Malloc and return an NT devicemode.
2663 ****************************************************************************/
2665 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2668 char adevice[MAXDEVICENAME];
2669 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2671 if (nt_devmode == NULL) {
2672 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2676 ZERO_STRUCTP(nt_devmode);
2678 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2679 fstrcpy(nt_devmode->devicename, adevice);
2681 fstrcpy(nt_devmode->formname, "Letter");
2683 nt_devmode->specversion = 0x0401;
2684 nt_devmode->driverversion = 0x0400;
2685 nt_devmode->size = 0x00DC;
2686 nt_devmode->driverextra = 0x0000;
2687 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2688 DEFAULTSOURCE | COPIES | SCALE |
2689 PAPERSIZE | ORIENTATION;
2690 nt_devmode->orientation = 1;
2691 nt_devmode->papersize = PAPER_LETTER;
2692 nt_devmode->paperlength = 0;
2693 nt_devmode->paperwidth = 0;
2694 nt_devmode->scale = 0x64;
2695 nt_devmode->copies = 1;
2696 nt_devmode->defaultsource = BIN_FORMSOURCE;
2697 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2698 nt_devmode->color = COLOR_MONOCHROME;
2699 nt_devmode->duplex = DUP_SIMPLEX;
2700 nt_devmode->yresolution = 0;
2701 nt_devmode->ttoption = TT_SUBDEV;
2702 nt_devmode->collate = COLLATE_FALSE;
2703 nt_devmode->icmmethod = 0;
2704 nt_devmode->icmintent = 0;
2705 nt_devmode->mediatype = 0;
2706 nt_devmode->dithertype = 0;
2708 /* non utilisés par un driver d'imprimante */
2709 nt_devmode->logpixels = 0;
2710 nt_devmode->bitsperpel = 0;
2711 nt_devmode->pelswidth = 0;
2712 nt_devmode->pelsheight = 0;
2713 nt_devmode->displayflags = 0;
2714 nt_devmode->displayfrequency = 0;
2715 nt_devmode->reserved1 = 0;
2716 nt_devmode->reserved2 = 0;
2717 nt_devmode->panningwidth = 0;
2718 nt_devmode->panningheight = 0;
2720 nt_devmode->nt_dev_private = NULL;
2724 /****************************************************************************
2725 Deepcopy an NT devicemode.
2726 ****************************************************************************/
2728 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2730 NT_DEVICEMODE *new_nt_devicemode = NULL;
2732 if ( !nt_devicemode )
2735 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2736 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2740 new_nt_devicemode->nt_dev_private = NULL;
2741 if (nt_devicemode->nt_dev_private != NULL) {
2742 if ((new_nt_devicemode->nt_dev_private = (uint8 *)memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2743 SAFE_FREE(new_nt_devicemode);
2744 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2749 return new_nt_devicemode;
2752 /****************************************************************************
2753 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2754 ****************************************************************************/
2756 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2758 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2760 if(nt_devmode == NULL)
2763 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2765 SAFE_FREE(nt_devmode->nt_dev_private);
2766 SAFE_FREE(*devmode_ptr);
2769 /****************************************************************************
2770 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2771 ****************************************************************************/
2773 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2775 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2780 free_nt_devicemode(&info->devmode);
2782 TALLOC_FREE( *info_ptr );
2786 /****************************************************************************
2787 ****************************************************************************/
2788 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2792 NT_DEVICEMODE devmode;
2794 ZERO_STRUCT(devmode);
2796 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2798 if (!*nt_devmode) return len;
2800 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2804 &devmode.specversion,
2805 &devmode.driverversion,
2807 &devmode.driverextra,
2808 &devmode.orientation,
2810 &devmode.paperlength,
2811 &devmode.paperwidth,
2814 &devmode.defaultsource,
2815 &devmode.printquality,
2818 &devmode.yresolution,
2824 &devmode.bitsperpel,
2826 &devmode.pelsheight,
2827 &devmode.displayflags,
2828 &devmode.displayfrequency,
2832 &devmode.dithertype,
2835 &devmode.panningwidth,
2836 &devmode.panningheight,
2837 &devmode.nt_dev_private);
2839 if (devmode.nt_dev_private) {
2840 /* the len in tdb_unpack is an int value and
2841 * devmode.driverextra is only a short
2843 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2844 devmode.driverextra=(uint16)extra_len;
2846 /* check to catch an invalid TDB entry so we don't segfault */
2847 if (devmode.driverextra == 0) {
2848 devmode.nt_dev_private = NULL;
2852 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2854 SAFE_FREE(devmode.nt_dev_private);
2858 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2859 if (devmode.nt_dev_private)
2860 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2865 /****************************************************************************
2866 Allocate and initialize a new slot.
2867 ***************************************************************************/
2869 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2874 if ( !name || !data )
2877 /* allocate another slot in the NT_PRINTER_KEY array */
2879 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2880 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2886 key_index = data->num_keys;
2888 /* initialze new key */
2890 data->keys[key_index].name = talloc_strdup( data, name );
2892 if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
2897 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2902 /****************************************************************************
2903 search for a registry key name in the existing printer data
2904 ***************************************************************************/
2906 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2910 for ( i=0; i<data->num_keys; i++ ) {
2911 if ( strequal( data->keys[i].name, name ) ) {
2913 /* cleanup memory */
2915 TALLOC_FREE( data->keys[i].name );
2916 TALLOC_FREE( data->keys[i].values );
2918 /* if not the end of the array, move remaining elements down one slot */
2921 if ( data->num_keys && (i < data->num_keys) )
2922 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2929 return data->num_keys;
2932 /****************************************************************************
2933 search for a registry key name in the existing printer data
2934 ***************************************************************************/
2936 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2941 if ( !data || !name )
2944 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2946 /* loop over all existing keys */
2948 for ( i=0; i<data->num_keys; i++ ) {
2949 if ( strequal(data->keys[i].name, name) ) {
2950 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2960 /****************************************************************************
2961 ***************************************************************************/
2963 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2967 int num_subkeys = 0;
2969 fstring *subkeys_ptr = NULL;
2980 /* special case of asking for the top level printer data registry key names */
2982 if ( strlen(key) == 0 ) {
2983 for ( i=0; i<data->num_keys; i++ ) {
2985 /* found a match, so allocate space and copy the name */
2987 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2988 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2993 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
3000 /* asking for the subkeys of some key */
3001 /* subkey paths are stored in the key name using '\' as the delimiter */
3003 for ( i=0; i<data->num_keys; i++ ) {
3004 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
3006 /* if we found the exact key, then break */
3007 key_len = strlen( key );
3008 if ( strlen(data->keys[i].name) == key_len )
3011 /* get subkey path */
3013 p = data->keys[i].name + key_len;
3016 fstrcpy( subkeyname, p );
3017 if ( (p = strchr( subkeyname, '\\' )) )
3020 /* don't add a key more than once */
3022 for ( j=0; j<num_subkeys; j++ ) {
3023 if ( strequal( subkeys_ptr[j], subkeyname ) )
3027 if ( j != num_subkeys )
3030 /* found a match, so allocate space and copy the name */
3032 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3033 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3038 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
3044 /* return error if the key was not found */
3046 if ( i == data->num_keys ) {
3047 SAFE_FREE(subkeys_ptr);
3052 /* tag off the end */
3055 fstrcpy(subkeys_ptr[num_subkeys], "" );
3057 *subkeys = subkeys_ptr;
3063 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
3066 smb_ucs2_t conv_str[1024];
3069 regval_ctr_delvalue(ctr, val_name);
3070 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
3071 STR_TERMINATE | STR_NOALIGN);
3072 regval_ctr_addvalue(ctr, val_name, REG_SZ,
3073 (char *) conv_str, str_size);
3076 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
3079 regval_ctr_delvalue(ctr, val_name);
3080 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
3081 (char *) &dword, sizeof(dword));
3084 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
3087 uint8 bin_bool = (b ? 1 : 0);
3088 regval_ctr_delvalue(ctr, val_name);
3089 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
3090 (char *) &bin_bool, sizeof(bin_bool));
3093 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
3094 const char *multi_sz)
3096 smb_ucs2_t *conv_strs = NULL;
3099 /* a multi-sz has to have a null string terminator, i.e., the last
3100 string must be followed by two nulls */
3101 str_size = strlen(multi_sz) + 2;
3102 conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
3107 /* Change to byte units. */
3108 str_size *= sizeof(smb_ucs2_t);
3109 push_ucs2(NULL, conv_strs, multi_sz, str_size,
3110 STR_TERMINATE | STR_NOALIGN);
3112 regval_ctr_delvalue(ctr, val_name);
3113 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
3114 (char *) conv_strs, str_size);
3115 safe_free(conv_strs);
3119 /****************************************************************************
3120 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3122 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3123 * @return bool indicating success or failure
3124 ***************************************************************************/
3126 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
3128 REGVAL_CTR *ctr = NULL;
3130 const char *dnssuffix;
3131 char *allocated_string = NULL;
3132 const char *ascii_str;
3135 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3136 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3137 ctr = info2->data->keys[i].values;
3139 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3140 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3142 /* we make the assumption that the netbios name is the same
3143 as the DNS name sinc ethe former will be what we used to
3146 dnssuffix = get_mydnsdomname(talloc_tos());
3147 if (dnssuffix && *dnssuffix) {
3148 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3150 fstrcpy( longname, global_myname() );
3153 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3155 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
3156 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3157 SAFE_FREE(allocated_string);
3159 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3160 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3161 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3162 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3163 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3164 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3165 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3166 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3167 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3169 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3170 (info2->attributes &
3171 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3173 switch (info2->attributes & 0x3) {
3175 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3178 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3181 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3184 ascii_str = "unknown";
3186 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3191 /*****************************************************************
3192 ****************************************************************/
3194 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3198 REGVAL_CTR *ctr=NULL;
3199 UNISTR2 unistr_guid;
3201 /* find the DsSpooler key */
3202 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3203 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3204 ctr = info2->data->keys[i].values;
3206 regval_ctr_delvalue(ctr, "objectGUID");
3208 /* We used to store this as a REG_BINARY but that causes
3211 ZERO_STRUCT( unistr_guid );
3213 init_unistr2( &unistr_guid, smb_uuid_string(talloc_tos(), guid),
3214 UNI_STR_TERMINATE );
3216 regval_ctr_addvalue(ctr, "objectGUID", REG_SZ,
3217 (char *)unistr_guid.buffer,
3218 unistr_guid.uni_max_len*2);
3222 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3223 NT_PRINTER_INFO_LEVEL *printer)
3227 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3228 char *srv_dn_utf8, **srv_cn_utf8;
3231 const char *attrs[] = {"objectGUID", NULL};
3233 WERROR win_rc = WERR_OK;
3235 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3237 /* figure out where to publish */
3238 ads_find_machine_acct(ads, &res, global_myname());
3240 /* We use ldap_get_dn here as we need the answer
3241 * in utf8 to call ldap_explode_dn(). JRA. */
3243 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3246 return WERR_SERVER_UNAVAILABLE;
3248 ads_msgfree(ads, res);
3249 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3251 ldap_memfree(srv_dn_utf8);
3253 return WERR_SERVER_UNAVAILABLE;
3255 /* Now convert to CH_UNIX. */
3256 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
3257 ldap_memfree(srv_dn_utf8);
3258 ldap_memfree(srv_cn_utf8);
3260 return WERR_SERVER_UNAVAILABLE;
3262 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
3263 ldap_memfree(srv_dn_utf8);
3264 ldap_memfree(srv_cn_utf8);
3267 return WERR_SERVER_UNAVAILABLE;
3270 ldap_memfree(srv_dn_utf8);
3271 ldap_memfree(srv_cn_utf8);
3273 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3274 if (!srv_cn_escaped) {
3275 SAFE_FREE(srv_cn_0);
3276 ldap_memfree(srv_dn_utf8);
3278 return WERR_SERVER_UNAVAILABLE;
3280 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3281 if (!sharename_escaped) {
3282 SAFE_FREE(srv_cn_escaped);
3283 SAFE_FREE(srv_cn_0);
3284 ldap_memfree(srv_dn_utf8);
3286 return WERR_SERVER_UNAVAILABLE;
3290 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3293 SAFE_FREE(srv_cn_0);
3294 SAFE_FREE(srv_cn_escaped);
3295 SAFE_FREE(sharename_escaped);
3297 /* build the ads mods */
3298 ctx = talloc_init("nt_printer_publish_ads");
3304 mods = ads_init_mods(ctx);
3308 talloc_destroy(ctx);
3312 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3313 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3314 printer->info_2->sharename);
3317 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3318 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3320 for (i=0; mods[i] != 0; i++)
3322 mods[i] = (LDAPMod *)-1;
3323 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3326 if (!ADS_ERR_OK(ads_rc))
3327 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3329 talloc_destroy(ctx);
3331 /* retreive the guid and store it locally */
3332 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3334 ads_pull_guid(ads, res, &guid);
3335 ads_msgfree(ads, res);
3336 store_printer_guid(printer->info_2, guid);
3337 win_rc = mod_a_printer(printer, 2);
3344 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3345 NT_PRINTER_INFO_LEVEL *printer)
3349 char *prt_dn = NULL;
3351 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3353 /* remove the printer from the directory */
3354 ads_rc = ads_find_printer_on_server(ads, &res,
3355 printer->info_2->sharename, global_myname());
3357 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
3358 prt_dn = ads_get_dn(ads, res);
3360 ads_msgfree(ads, res);
3363 ads_rc = ads_del_dn(ads, prt_dn);
3364 ads_memfree(ads, prt_dn);
3367 ads_msgfree(ads, res);
3371 /****************************************************************************
3372 * Publish a printer in the directory
3374 * @param snum describing printer service
3375 * @return WERROR indicating status of publishing
3376 ***************************************************************************/
3378 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3381 ADS_STRUCT *ads = NULL;
3382 NT_PRINTER_INFO_LEVEL *printer = NULL;
3385 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3386 if (!W_ERROR_IS_OK(win_rc))
3390 case SPOOL_DS_PUBLISH:
3391 case SPOOL_DS_UPDATE:
3392 /* set the DsSpooler info and attributes */
3393 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3394 win_rc = WERR_NOMEM;
3398 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3400 case SPOOL_DS_UNPUBLISH:
3401 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3404 win_rc = WERR_NOT_SUPPORTED;
3408 win_rc = mod_a_printer(printer, 2);
3409 if (!W_ERROR_IS_OK(win_rc)) {
3410 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3414 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3416 DEBUG(3, ("ads_init() failed\n"));
3417 win_rc = WERR_SERVER_UNAVAILABLE;
3420 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3421 SAFE_FREE(ads->auth.password);
3422 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3425 /* ads_connect() will find the DC for us */
3426 ads_rc = ads_connect(ads);
3427 if (!ADS_ERR_OK(ads_rc)) {
3428 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3429 win_rc = WERR_ACCESS_DENIED;
3434 case SPOOL_DS_PUBLISH:
3435 case SPOOL_DS_UPDATE:
3436 win_rc = nt_printer_publish_ads(ads, printer);
3438 case SPOOL_DS_UNPUBLISH:
3439 win_rc = nt_printer_unpublish_ads(ads, printer);
3444 free_a_printer(&printer, 2);
3449 WERROR check_published_printers(void)
3452 ADS_STRUCT *ads = NULL;
3454 int n_services = lp_numservices();
3455 NT_PRINTER_INFO_LEVEL *printer = NULL;
3457 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3459 DEBUG(3, ("ads_init() failed\n"));
3460 return WERR_SERVER_UNAVAILABLE;
3462 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3463 SAFE_FREE(ads->auth.password);
3464 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3467 /* ads_connect() will find the DC for us */
3468 ads_rc = ads_connect(ads);
3469 if (!ADS_ERR_OK(ads_rc)) {
3470 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3472 ads_kdestroy("MEMORY:prtpub_cache");
3473 return WERR_ACCESS_DENIED;
3476 for (snum = 0; snum < n_services; snum++) {
3477 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3480 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3481 lp_servicename(snum))) &&
3482 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3483 nt_printer_publish_ads(ads, printer);
3485 free_a_printer(&printer, 2);
3489 ads_kdestroy("MEMORY:prtpub_cache");
3493 bool is_printer_published(Printer_entry *print_hnd, int snum,
3496 NT_PRINTER_INFO_LEVEL *printer = NULL;
3498 REGISTRY_VALUE *guid_val;
3503 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3505 if (!W_ERROR_IS_OK(win_rc) ||
3506 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3507 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3508 !(ctr = printer->info_2->data->keys[i].values) ||
3509 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3511 free_a_printer(&printer, 2);
3515 /* fetching printer guids really ought to be a separate function. */
3520 /* We used to store the guid as REG_BINARY, then swapped
3521 to REG_SZ for Vista compatibility so check for both */
3523 switch ( regval_type(guid_val) ){
3525 rpcstr_pull( guid_str, regval_data_p(guid_val),
3526 sizeof(guid_str)-1, -1, STR_TERMINATE );
3527 ret = smb_string_to_uuid( guid_str, guid );
3530 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3534 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3537 DEBUG(0,("is_printer_published: GUID value stored as "
3538 "invaluid type (%d)\n", regval_type(guid_val) ));
3543 free_a_printer(&printer, 2);
3547 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3552 WERROR check_published_printers(void)
3557 bool is_printer_published(Printer_entry *print_hnd, int snum,
3562 #endif /* HAVE_ADS */
3564 /****************************************************************************
3565 ***************************************************************************/
3567 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3569 NT_PRINTER_DATA *data;
3571 int removed_keys = 0;
3575 empty_slot = data->num_keys;
3578 return WERR_INVALID_PARAM;
3580 /* remove all keys */
3582 if ( !strlen(key) ) {
3584 TALLOC_FREE( data );
3588 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3594 /* remove a specific key (and all subkeys) */
3596 for ( i=0; i<data->num_keys; i++ ) {
3597 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3598 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3599 data->keys[i].name));
3601 TALLOC_FREE( data->keys[i].name );
3602 TALLOC_FREE( data->keys[i].values );
3604 /* mark the slot as empty */
3606 ZERO_STRUCTP( &data->keys[i] );
3610 /* find the first empty slot */
3612 for ( i=0; i<data->num_keys; i++ ) {
3613 if ( !data->keys[i].name ) {
3620 if ( i == data->num_keys )
3621 /* nothing was removed */
3622 return WERR_INVALID_PARAM;
3624 /* move everything down */
3626 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3627 if ( data->keys[i].name ) {
3628 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3629 ZERO_STRUCTP( &data->keys[i] );
3637 data->num_keys -= removed_keys;
3639 /* sanity check to see if anything is left */
3641 if ( !data->num_keys ) {
3642 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3644 SAFE_FREE( data->keys );
3645 ZERO_STRUCTP( data );
3651 /****************************************************************************
3652 ***************************************************************************/
3654 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3656 WERROR result = WERR_OK;
3659 /* we must have names on non-zero length */
3661 if ( !key || !*key|| !value || !*value )
3662 return WERR_INVALID_NAME;
3664 /* find the printer key first */
3666 key_index = lookup_printerkey( p2->data, key );
3667 if ( key_index == -1 )
3670 /* make sure the value exists so we can return the correct error code */
3672 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3673 return WERR_BADFILE;
3675 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3677 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3683 /****************************************************************************
3684 ***************************************************************************/
3686 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3687 uint32 type, uint8 *data, int real_len )
3689 WERROR result = WERR_OK;
3692 /* we must have names on non-zero length */
3694 if ( !key || !*key|| !value || !*value )
3695 return WERR_INVALID_NAME;
3697 /* find the printer key first */
3699 key_index = lookup_printerkey( p2->data, key );
3700 if ( key_index == -1 )
3701 key_index = add_new_printer_key( p2->data, key );
3703 if ( key_index == -1 )
3706 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3707 type, (const char *)data, real_len );
3709 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3710 key, value, type, real_len ));
3715 /****************************************************************************
3716 ***************************************************************************/
3718 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3722 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3725 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3728 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3731 /****************************************************************************
3732 Unpack a list of registry values frem the TDB
3733 ***************************************************************************/
3735 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3740 const char *valuename = NULL;
3741 const char *keyname = NULL;
3745 REGISTRY_VALUE *regval_p;
3748 /* add the "PrinterDriverData" key first for performance reasons */
3750 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3752 /* loop and unpack the rest of the registry values */
3756 /* check to see if there are any more registry values */
3759 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3763 /* unpack the next regval */
3765 len += tdb_unpack(buf+len, buflen-len, "fdB",
3771 /* lookup for subkey names which have a type of REG_NONE */
3772 /* there's no data with this entry */
3774 if ( type == REG_NONE ) {
3775 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3776 add_new_printer_key( printer_data, string );
3781 * break of the keyname from the value name.
3782 * Valuenames can have embedded '\'s so be careful.
3783 * only support one level of keys. See the
3784 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3788 str = strchr_m( string, '\\');
3790 /* Put in "PrinterDriverData" is no key specified */
3793 keyname = SPOOL_PRINTERDATA_KEY;
3802 /* see if we need a new key */
3804 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3805 key_index = add_new_printer_key( printer_data, keyname );
3807 if ( key_index == -1 ) {
3808 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3813 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3815 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3816 Thanks to Martin Zielinski for the hint. */
3818 if ( type == REG_BINARY &&
3819 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3820 strequal( valuename, "objectGUID" ) )
3823 UNISTR2 unistr_guid;
3825 ZERO_STRUCT( unistr_guid );
3827 /* convert the GUID to a UNICODE string */
3829 memcpy( &guid, data_p, sizeof(struct GUID) );
3831 init_unistr2( &unistr_guid,
3832 smb_uuid_string(talloc_tos(), guid),
3833 UNI_STR_TERMINATE );
3835 regval_ctr_addvalue( printer_data->keys[key_index].values,
3837 (const char *)unistr_guid.buffer,
3838 unistr_guid.uni_str_len*2 );
3843 regval_ctr_addvalue( printer_data->keys[key_index].values,
3844 valuename, type, (const char *)data_p,
3848 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3855 /****************************************************************************
3856 ***************************************************************************/
3858 static char *last_from;
3859 static char *last_to;
3861 static const char *get_last_from(void)
3869 static const char *get_last_to(void)
3877 static bool set_last_from_to(const char *from, const char *to)
3879 char *orig_from = last_from;
3880 char *orig_to = last_to;
3882 last_from = SMB_STRDUP(from);
3883 last_to = SMB_STRDUP(to);
3885 SAFE_FREE(orig_from);
3888 if (!last_from || !last_to) {
3889 SAFE_FREE(last_from);
3896 static void map_to_os2_driver(fstring drivername)
3898 char *mapfile = lp_os2_driver_map();
3899 char **lines = NULL;
3903 if (!strlen(drivername))
3909 if (strequal(drivername,get_last_from())) {
3910 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3911 drivername,get_last_to()));
3912 fstrcpy(drivername,get_last_to());
3916 lines = file_lines_load(mapfile, &numlines,0);
3917 if (numlines == 0 || lines == NULL) {
3918 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3923 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3925 for( i = 0; i < numlines; i++) {
3926 char *nt_name = lines[i];
3927 char *os2_name = strchr(nt_name,'=');
3934 while (isspace(*nt_name))
3937 if (!*nt_name || strchr("#;",*nt_name))
3941 int l = strlen(nt_name);
3942 while (l && isspace(nt_name[l-1])) {
3948 while (isspace(*os2_name))
3952 int l = strlen(os2_name);
3953 while (l && isspace(os2_name[l-1])) {
3959 if (strequal(nt_name,drivername)) {
3960 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3961 set_last_from_to(drivername,os2_name);
3962 fstrcpy(drivername,os2_name);
3963 file_lines_free(lines);
3968 file_lines_free(lines);
3971 /****************************************************************************
3972 Get a default printer info 2 struct.
3973 ****************************************************************************/
3974 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
3976 int snum = lp_servicenumber(sharename);
3978 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3979 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3980 servername, sharename);
3981 fstrcpy(info->sharename, sharename);
3982 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3984 /* by setting the driver name to an empty string, a local NT admin
3985 can now run the **local** APW to install a local printer driver
3986 for a Samba shared printer in 2.2. Without this, drivers **must** be
3987 installed on the Samba server for NT clients --jerry */
3988 #if 0 /* JERRY --do not uncomment-- */
3989 if (!*info->drivername)
3990 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3994 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3996 strlcpy(info->comment, "", sizeof(info->comment));
3997 fstrcpy(info->printprocessor, "winprint");
3998 fstrcpy(info->datatype, "RAW");
4001 if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4002 /* Pull the location and comment strings from cups if we don't
4004 if ( !strlen(info->location) || !strlen(info->comment) )
4005 cups_pull_comment_location( info );
4009 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
4011 info->starttime = 0; /* Minutes since 12:00am GMT */
4012 info->untiltime = 0; /* Minutes since 12:00am GMT */
4014 info->default_priority = 1;
4015 info->setuptime = (uint32)time(NULL);
4018 * I changed this as I think it is better to have a generic
4019 * DEVMODE than to crash Win2k explorer.exe --jerry
4020 * See the HP Deskjet 990c Win2k drivers for an example.
4022 * However the default devmode appears to cause problems
4023 * with the HP CLJ 8500 PCL driver. Hence the addition of
4024 * the "default devmode" parameter --jerry 22/01/2002
4027 if (lp_default_devmode(snum)) {
4028 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
4032 info->devmode = NULL;
4035 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4043 free_nt_devicemode(&info->devmode);
4045 return WERR_ACCESS_DENIED;
4048 /****************************************************************************
4049 ****************************************************************************/
4050 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
4053 int snum = lp_servicenumber(sharename);
4054 TDB_DATA kbuf, dbuf;
4055 fstring printername;
4056 char adevice[MAXDEVICENAME];
4057 char *comment = NULL;
4059 kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4061 dbuf = tdb_fetch(tdb_printers, kbuf);
4063 return get_a_printer_2_default(info, servername, sharename);
4066 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4069 &info->default_priority,
4076 &info->c_setprinter,
4086 info->printprocessor,
4091 strlcpy(info->comment, comment, sizeof(info->comment));
4095 /* Samba has to have shared raw drivers. */
4096 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4097 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4099 /* Restore the stripped strings. */
4100 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4102 if ( lp_force_printername(snum) ) {
4103 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4105 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4108 fstrcpy(info->printername, printername);
4111 if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4112 /* Pull the location and comment strings from cups if we don't
4114 if ( !strlen(info->location) || !strlen(info->comment) )
4115 cups_pull_comment_location( info );
4119 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4122 * Some client drivers freak out if there is a NULL devmode
4123 * (probably the driver is not checking before accessing
4124 * the devmode pointer) --jerry
4126 * See comments in get_a_printer_2_default()
4129 if (lp_default_devmode(snum) && !info->devmode) {
4130 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4132 info->devmode = construct_nt_devicemode(printername);
4135 slprintf( adevice, sizeof(adevice), "%s", info->printername );
4136 if (info->devmode) {
4137 fstrcpy(info->devmode->devicename, adevice);
4140 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4141 DEBUG(0,("unpack_values: talloc() failed!\n"));
4142 SAFE_FREE(dbuf.dptr);
4145 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4147 /* This will get the current RPC talloc context, but we should be
4148 passing this as a parameter... fixme... JRA ! */
4150 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4151 SAFE_FREE(dbuf.dptr);
4155 /* Fix for OS/2 drivers. */
4157 if (get_remote_arch() == RA_OS2) {
4158 map_to_os2_driver(info->drivername);
4161 SAFE_FREE(dbuf.dptr);
4163 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4164 sharename, info->printername, info->drivername));
4169 /****************************************************************************
4170 Debugging function, dump at level 6 the struct in the logs.
4171 ****************************************************************************/
4172 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4175 NT_PRINTER_INFO_LEVEL_2 *info2;
4177 DEBUG(106,("Dumping printer at level [%d]\n", level));
4182 if (printer->info_2 == NULL)
4186 info2=printer->info_2;
4188 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4189 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4190 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4191 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4192 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4193 DEBUGADD(106,("status:[%d]\n", info2->status));
4194 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4195 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4196 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4197 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4198 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4200 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4201 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4202 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4203 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4204 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4205 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4206 DEBUGADD(106,("location:[%s]\n", info2->location));
4207 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4208 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4209 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4210 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4216 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4224 /****************************************************************************
4225 Update the changeid time.
4226 This is SO NASTY as some drivers need this to change, others need it
4227 static. This value will change every second, and I must hope that this
4228 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4230 ****************************************************************************/
4232 static uint32 rev_changeid(void)
4236 get_process_uptime(&tv);
4239 /* Return changeid as msec since spooler restart */
4240 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4243 * This setting seems to work well but is too untested
4244 * to replace the above calculation. Left in for experiementation
4245 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4247 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4253 * The function below are the high level ones.
4254 * only those ones must be called from the spoolss code.
4258 /****************************************************************************
4259 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4260 ****************************************************************************/
4262 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4266 dump_a_printer(printer, level);
4272 * Update the changestamp. Emperical tests show that the
4273 * ChangeID is always updated,but c_setprinter is
4274 * global spooler variable (not per printer).
4277 /* ChangeID **must** be increasing over the lifetime
4278 of client's spoolss service in order for the
4279 client's cache to show updates */
4281 printer->info_2->changeid = rev_changeid();
4284 * Because one day someone will ask:
4285 * NT->NT An admin connection to a remote
4286 * printer show changes imeediately in
4287 * the properities dialog
4289 * A non-admin connection will only show the
4290 * changes after viewing the properites page
4291 * 2 times. Seems to be related to a
4292 * race condition in the client between the spooler
4293 * updating the local cache and the Explorer.exe GUI
4294 * actually displaying the properties.
4296 * This is fixed in Win2k. admin/non-admin
4297 * connections both display changes immediately.
4302 result=update_a_printer_2(printer->info_2);
4306 result=WERR_UNKNOWN_LEVEL;
4313 /****************************************************************************
4314 Initialize printer devmode & data with previously saved driver init values.
4315 ****************************************************************************/
4317 static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4322 NT_PRINTER_INFO_LEVEL_2 info;
4328 * Delete any printer data 'values' already set. When called for driver
4329 * replace, there will generally be some, but during an add printer, there
4330 * should not be any (if there are delete them).
4333 if ( info_ptr->data )
4334 delete_all_printer_data( info_ptr, "" );
4336 if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX,
4337 info_ptr->drivername) < 0) {
4341 dbuf = tdb_fetch_bystring(tdb_drivers, key);
4344 * When changing to a driver that has no init info in the tdb, remove
4345 * the previous drivers init info and leave the new on blank.
4347 free_nt_devicemode(&info_ptr->devmode);
4354 * Get the saved DEVMODE..
4357 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4360 * The saved DEVMODE contains the devicename from the printer used during
4361 * the initialization save. Change it to reflect the new printer.
4364 if ( info.devmode ) {
4365 ZERO_STRUCT(info.devmode->devicename);
4366 fstrcpy(info.devmode->devicename, info_ptr->printername);
4370 * NT/2k does not change out the entire DeviceMode of a printer
4371 * when changing the driver. Only the driverextra, private, &
4372 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
4374 * Later examination revealed that Windows NT/2k does reset the
4375 * the printer's device mode, bit **only** when you change a
4376 * property of the device mode such as the page orientation.
4381 /* Bind the saved DEVMODE to the new the printer */
4383 free_nt_devicemode(&info_ptr->devmode);
4384 info_ptr->devmode = info.devmode;
4386 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4387 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4389 /* Add the printer data 'values' to the new printer */
4391 if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4392 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4396 len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4398 SAFE_FREE(dbuf.dptr);
4403 /****************************************************************************
4404 Initialize printer devmode & data with previously saved driver init values.
4405 When a printer is created using AddPrinter, the drivername bound to the
4406 printer is used to lookup previously saved driver initialization info, which
4407 is bound to the new printer.
4408 ****************************************************************************/
4410 bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4412 bool result = False;
4416 result = set_driver_init_2(printer->info_2);
4420 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4428 /****************************************************************************
4429 Delete driver init data stored for a specified driver
4430 ****************************************************************************/
4432 bool del_driver_init(char *drivername)
4437 if (!drivername || !*drivername) {
4438 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4442 if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, drivername) < 0) {
4446 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n",
4449 ret = (tdb_delete_bystring(tdb_drivers, key) == 0);
4454 /****************************************************************************
4455 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4456 in the tdb. Note: this is different from the driver entry and the printer
4457 entry. There should be a single driver init entry for each driver regardless
4458 of whether it was installed from NT or 2K. Technically, they should be
4459 different, but they work out to the same struct.
4460 ****************************************************************************/
4462 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4466 int buflen, len, ret;
4475 len += pack_devicemode(info->devmode, buf+len, buflen-len);
4477 retlen = pack_values( info->data, buf+len, buflen-len );
4485 buf = (uint8 *)SMB_REALLOC(buf, len);
4487 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4496 if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, info->drivername) < 0) {
4504 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4508 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4512 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4513 info->sharename, info->drivername));
4518 /****************************************************************************
4519 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4520 ****************************************************************************/
4522 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4526 dump_a_printer(printer, level);
4530 result = update_driver_init_2(printer->info_2);
4540 /****************************************************************************
4541 Convert the printer data value, a REG_BINARY array, into an initialization
4542 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4543 got to keep the endians happy :).
4544 ****************************************************************************/
4546 static bool convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4548 bool result = False;
4552 ZERO_STRUCT(devmode);
4554 prs_init(&ps, 0, ctx, UNMARSHALL);
4555 ps.data_p = (char *)data;
4556 ps.buffer_size = data_len;
4558 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4559 result = convert_devicemode("", &devmode, &nt_devmode);
4561 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4566 /****************************************************************************
4567 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4569 1. Use the driver's config DLL to this UNC printername and:
4570 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4571 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4572 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4574 The last step triggers saving the "driver initialization" information for
4575 this printer into the tdb. Later, new printers that use this driver will
4576 have this initialization information bound to them. This simulates the
4577 driver initialization, as if it had run on the Samba server (as it would
4580 The Win32 client side code requirement sucks! But until we can run arbitrary
4581 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4583 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4584 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4585 about it and you will realize why. JRR 010720
4586 ****************************************************************************/
4588 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4590 WERROR status = WERR_OK;
4591 TALLOC_CTX *ctx = NULL;
4592 NT_DEVICEMODE *nt_devmode = NULL;
4593 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4596 * When the DEVMODE is already set on the printer, don't try to unpack it.
4598 DEBUG(8,("save_driver_init_2: Enter...\n"));
4600 if ( !printer->info_2->devmode && data_len ) {
4602 * Set devmode on printer info, so entire printer initialization can be
4606 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4609 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4610 status = WERR_NOMEM;
4614 ZERO_STRUCTP(nt_devmode);
4617 * The DEVMODE is held in the 'data' component of the param in raw binary.
4618 * Convert it to to a devmode structure
4620 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4621 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4622 status = WERR_INVALID_PARAM;
4626 printer->info_2->devmode = nt_devmode;
4630 * Pack up and add (or update) the DEVMODE and any current printer data to
4631 * a 'driver init' element in the tdb
4635 if ( update_driver_init(printer, 2) != 0 ) {
4636 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4637 status = WERR_NOMEM;
4642 * If driver initialization info was successfully saved, set the current
4643 * printer to match it. This allows initialization of the current printer
4644 * as well as the driver.
4646 status = mod_a_printer(printer, 2);
4647 if (!W_ERROR_IS_OK(status)) {
4648 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4649 printer->info_2->printername));
4653 talloc_destroy(ctx);
4654 free_nt_devicemode( &nt_devmode );
4656 printer->info_2->devmode = tmp_devmode;
4661 /****************************************************************************
4662 Update the driver init info (DEVMODE and specifics) for a printer
4663 ****************************************************************************/
4665 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4667 WERROR status = WERR_OK;
4671 status = save_driver_init_2( printer, data, data_len );
4674 status = WERR_UNKNOWN_LEVEL;
4681 /****************************************************************************
4682 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4684 Previously the code had a memory allocation problem because it always
4685 used the TALLOC_CTX from the Printer_entry*. This context lasts
4686 as a long as the original handle is open. So if the client made a lot
4687 of getprinter[data]() calls, the memory usage would climb. Now we use
4688 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4689 still use the Printer_entry->ctx for maintaining the cache copy though
4690 since that object must live as long as the handle by definition.
4693 ****************************************************************************/
4695 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4696 const char *sharename)
4701 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4703 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4704 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4710 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4711 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4712 TALLOC_FREE( *pp_printer );
4717 fstrcpy( servername, print_hnd->servername );
4719 fstrcpy( servername, "%L" );
4720 standard_sub_basic( "", "", servername,
4721 sizeof(servername)-1 );
4724 result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4727 /* we have a new printer now. Save it with this handle */
4729 if ( !W_ERROR_IS_OK(result) ) {
4730 TALLOC_FREE( *pp_printer );
4731 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4732 sharename, (unsigned int)level, dos_errstr(result)));
4736 dump_a_printer( *pp_printer, level);
4741 TALLOC_FREE( *pp_printer );
4742 return WERR_UNKNOWN_LEVEL;
4748 /****************************************************************************
4749 Deletes a NT_PRINTER_INFO_LEVEL struct.
4750 ****************************************************************************/
4752 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4754 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4761 if ( printer->info_2 )
4762 free_nt_printer_info_level_2(&printer->info_2);
4766 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4770 TALLOC_FREE(*pp_printer);
4775 /****************************************************************************
4776 ****************************************************************************/
4777 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4780 DEBUG(104,("adding a printer at level [%d]\n", level));
4781 dump_a_printer_driver(driver, level);
4785 result=add_a_printer_driver_3(driver.info_3);
4789 result=add_a_printer_driver_6(driver.info_6);
4799 /****************************************************************************
4800 ****************************************************************************/
4802 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4803 fstring drivername, const char *architecture, uint32 version)
4809 /* Sometime we just want any version of the driver */
4811 if ( version == DRIVER_ANY_VERSION ) {
4812 /* look for Win2k first and then for NT4 */
4813 result = get_a_printer_driver_3(&driver->info_3, drivername,
4816 if ( !W_ERROR_IS_OK(result) ) {
4817 result = get_a_printer_driver_3( &driver->info_3,
4818 drivername, architecture, 2 );
4821 result = get_a_printer_driver_3(&driver->info_3, drivername,
4822 architecture, version);
4831 if (W_ERROR_IS_OK(result))
4832 dump_a_printer_driver(*driver, level);
4837 /****************************************************************************
4838 ****************************************************************************/
4839 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4846 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4847 if (driver.info_3 != NULL)
4849 info3=driver.info_3;
4850 SAFE_FREE(info3->dependentfiles);
4851 ZERO_STRUCTP(info3);
4861 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4862 if (driver.info_6 != NULL) {
4863 info6=driver.info_6;
4864 SAFE_FREE(info6->dependentfiles);
4865 SAFE_FREE(info6->previousnames);
4866 ZERO_STRUCTP(info6);
4882 /****************************************************************************
4883 Determine whether or not a particular driver is currently assigned
4885 ****************************************************************************/
4887 bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4890 int n_services = lp_numservices();
4891 NT_PRINTER_INFO_LEVEL *printer = NULL;
4892 bool in_use = False;
4897 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4899 /* loop through the printers.tdb and check for the drivername */
4901 for (snum=0; snum<n_services && !in_use; snum++) {
4902 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4905 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4908 if ( strequal(info_3->name, printer->info_2->drivername) )
4911 free_a_printer( &printer, 2 );
4914 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4917 NT_PRINTER_DRIVER_INFO_LEVEL d;
4920 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4922 /* we can still remove the driver if there is one of
4923 "Windows NT x86" version 2 or 3 left */
4925 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4926 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4929 switch ( info_3->cversion ) {
4931 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4934 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4937 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4939 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4944 /* now check the error code */
4946 if ( W_ERROR_IS_OK(werr) ) {
4947 /* it's ok to remove the driver, we have other architctures left */
4949 free_a_printer_driver( d, 3 );
4953 /* report that the driver is not in use by default */
4959 /**********************************************************************
4960 Check to see if a ogiven file is in use by *info
4961 *********************************************************************/
4963 static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4970 if ( strequal(file, info->driverpath) )
4973 if ( strequal(file, info->datafile) )
4976 if ( strequal(file, info->configfile) )
4979 if ( strequal(file, info->helpfile) )
4982 /* see of there are any dependent files to examine */
4984 if ( !info->dependentfiles )
4987 while ( *info->dependentfiles[i] ) {
4988 if ( strequal(file, info->dependentfiles[i]) )
4997 /**********************************************************************
4998 Utility function to remove the dependent file pointed to by the
4999 input parameter from the list
5000 *********************************************************************/
5002 static void trim_dependent_file( fstring files[], int idx )
5005 /* bump everything down a slot */
5007 while( *files[idx+1] ) {
5008 fstrcpy( files[idx], files[idx+1] );
5017 /**********************************************************************
5018 Check if any of the files used by src are also used by drv
5019 *********************************************************************/
5021 static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
5022 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
5024 bool in_use = False;
5030 /* check each file. Remove it from the src structure if it overlaps */
5032 if ( drv_file_in_use(src->driverpath, drv) ) {
5034 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
5035 fstrcpy( src->driverpath, "" );
5038 if ( drv_file_in_use(src->datafile, drv) ) {
5040 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
5041 fstrcpy( src->datafile, "" );
5044 if ( drv_file_in_use(src->configfile, drv) ) {
5046 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
5047 fstrcpy( src->configfile, "" );
5050 if ( drv_file_in_use(src->helpfile, drv) ) {
5052 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
5053 fstrcpy( src->helpfile, "" );
5056 /* are there any dependentfiles to examine? */
5058 if ( !src->dependentfiles )
5061 while ( *src->dependentfiles[i] ) {
5062 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
5064 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
5065 trim_dependent_file( src->dependentfiles, i );
5073 /****************************************************************************
5074 Determine whether or not a particular driver files are currently being
5075 used by any other driver.
5077 Return value is True if any files were in use by other drivers
5078 and False otherwise.
5080 Upon return, *info has been modified to only contain the driver files
5081 which are not in use
5082 ****************************************************************************/
5084 bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
5089 fstring *list = NULL;
5090 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5095 version = info->cversion;
5097 /* loop over all driver versions */
5099 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
5101 /* get the list of drivers */
5104 ndrivers = get_ntdrivers(&list, info->environment, version);
5106 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
5107 ndrivers, info->environment, version));
5109 /* check each driver for overlap in files */
5111 for (i=0; i<ndrivers; i++) {
5112 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5114 ZERO_STRUCT(driver);
5116 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
5121 /* check if d2 uses any files from d1 */
5122 /* only if this is a different driver than the one being deleted */
5124 if ( !strequal(info->name, driver.info_3->name) ) {
5125 if ( trim_overlap_drv_files(info, driver.info_3) ) {
5126 free_a_printer_driver(driver, 3);
5132 free_a_printer_driver(driver, 3);
5137 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5139 driver.info_3 = info;
5141 if ( DEBUGLEVEL >= 20 )
5142 dump_a_printer_driver( driver, 3 );
5147 /****************************************************************************
5148 Actually delete the driver files. Make sure that
5149 printer_driver_files_in_use() return False before calling
5151 ****************************************************************************/
5153 static bool delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
5158 connection_struct *conn;
5167 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
5170 * Connect to the print$ share under the same account as the
5171 * user connected to the rpc pipe. Note we must be root to
5175 null_pw = data_blob_null;
5176 fstrcpy(res_type, "A:");
5178 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
5182 DEBUG(0,("delete_driver_files: Unable to connect\n"));
5186 if ( !CAN_WRITE(conn) ) {
5187 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5191 /* Save who we are - we are temporarily becoming the connection user. */
5193 if ( !become_user(conn, conn->vuid) ) {
5194 DEBUG(0,("delete_driver_files: Can't become user!\n"));
5198 /* now delete the files; must strip the '\print$' string from
5201 if ( *info_3->driverpath ) {
5202 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
5204 driver_unix_convert(conn,file,&st);
5205 DEBUG(10,("deleting driverfile [%s]\n", s));
5206 unlink_internals(conn, NULL, 0, file, False);
5210 if ( *info_3->configfile ) {
5211 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
5213 driver_unix_convert(conn,file,&st);
5214 DEBUG(10,("deleting configfile [%s]\n", s));
5215 unlink_internals(conn, NULL, 0, file, False);
5219 if ( *info_3->datafile ) {
5220 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
5222 driver_unix_convert(conn,file,&st);
5223 DEBUG(10,("deleting datafile [%s]\n", s));
5224 unlink_internals(conn, NULL, 0, file, False);
5228 if ( *info_3->helpfile ) {
5229 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
5231 driver_unix_convert(conn,file,&st);
5232 DEBUG(10,("deleting helpfile [%s]\n", s));
5233 unlink_internals(conn, NULL, 0, file, False);
5237 /* check if we are done removing files */
5239 if ( info_3->dependentfiles ) {
5240 while ( info_3->dependentfiles[i][0] ) {
5243 /* bypass the "\print$" portion of the path */
5245 if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
5247 driver_unix_convert(conn,file,&st);
5248 DEBUG(10,("deleting dependent file [%s]\n", file));
5249 unlink_internals(conn, NULL, 0, file, False);
5261 /****************************************************************************
5262 Remove a printer driver from the TDB. This assumes that the the driver was
5263 previously looked up.
5264 ***************************************************************************/
5266 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
5267 uint32 version, bool delete_files )
5272 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
5274 /* delete the tdb data first */
5276 arch = get_short_archi(info_3->environment);
5278 return WERR_UNKNOWN_PRINTER_DRIVER;
5280 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5281 arch, version, info_3->name) < 0) {
5285 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5286 key, delete_files ? "TRUE" : "FALSE" ));
5288 ctr.info_3 = info_3;
5289 dump_a_printer_driver( ctr, 3 );
5291 /* check if the driver actually exists for this environment */
5293 dbuf = tdb_fetch_bystring( tdb_drivers, key );
5295 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5297 return WERR_UNKNOWN_PRINTER_DRIVER;
5300 SAFE_FREE( dbuf.dptr );
5302 /* ok... the driver exists so the delete should return success */
5304 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5305 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5307 return WERR_ACCESS_DENIED;
5311 * now delete any associated files if delete_files == True
5312 * even if this part failes, we return succes because the
5313 * driver doesn not exist any more
5317 delete_driver_files( info_3, user );
5319 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5325 /****************************************************************************
5326 Store a security desc for a printer.
5327 ****************************************************************************/
5329 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5331 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5332 SEC_DESC_BUF *old_secdesc_ctr = NULL;
5334 bool prs_init_done = false;
5335 TALLOC_CTX *mem_ctx = NULL;
5339 mem_ctx = talloc_init("nt_printing_setsec");
5340 if (mem_ctx == NULL)
5343 /* The old owner and group sids of the security descriptor are not
5344 present when new ACEs are added or removed by changing printer
5345 permissions through NT. If they are NULL in the new security
5346 descriptor then copy them over from the old one. */
5348 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5349 DOM_SID *owner_sid, *group_sid;
5350 SEC_ACL *dacl, *sacl;
5351 SEC_DESC *psd = NULL;
5354 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5355 status = WERR_NOMEM;
5359 /* Pick out correct owner and group sids */
5361 owner_sid = secdesc_ctr->sd->owner_sid ?
5362 secdesc_ctr->sd->owner_sid :
5363 old_secdesc_ctr->sd->owner_sid;
5365 group_sid = secdesc_ctr->sd->group_sid ?
5366 secdesc_ctr->sd->group_sid :
5367 old_secdesc_ctr->sd->group_sid;
5369 dacl = secdesc_ctr->sd->dacl ?
5370 secdesc_ctr->sd->dacl :
5371 old_secdesc_ctr->sd->dacl;
5373 sacl = secdesc_ctr->sd->sacl ?
5374 secdesc_ctr->sd->sacl :
5375 old_secdesc_ctr->sd->sacl;
5377 /* Make a deep copy of the security descriptor */
5379 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5380 owner_sid, group_sid,
5386 status = WERR_NOMEM;
5390 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5393 if (!new_secdesc_ctr) {
5394 new_secdesc_ctr = secdesc_ctr;
5397 /* Store the security descriptor in a tdb */
5400 (uint32)ndr_size_security_descriptor(new_secdesc_ctr->sd, 0)
5401 + sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
5403 prs_init_done = true;
5405 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
5407 status = WERR_BADFUNC;
5411 kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5413 if (tdb_prs_store(tdb_printers, kbuf, &ps)==0) {
5416 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5417 status = WERR_BADFUNC;
5420 /* Free malloc'ed memory */
5424 if (prs_init_done) {
5428 talloc_destroy(mem_ctx);
5432 /****************************************************************************
5433 Construct a default security descriptor buffer for a printer.
5434 ****************************************************************************/
5436 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5438 SEC_ACE ace[5]; /* max number of ace entries */
5441 SEC_ACL *psa = NULL;
5442 SEC_DESC_BUF *sdb = NULL;
5443 SEC_DESC *psd = NULL;
5447 /* Create an ACE where Everyone is allowed to print */
5449 init_sec_access(&sa, PRINTER_ACE_PRINT);
5450 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5451 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5453 /* Add the domain admins group if we are a DC */
5456 DOM_SID domadmins_sid;
5458 sid_copy(&domadmins_sid, get_global_sam_sid());
5459 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5461 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5462 init_sec_ace(&ace[i++], &domadmins_sid,
5463 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5464 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5465 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5466 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5468 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5469 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5471 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5472 init_sec_ace(&ace[i++], &adm_sid,
5473 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5474 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5475 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5476 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5479 /* add BUILTIN\Administrators as FULL CONTROL */
5481 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5482 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5483 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5484 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5485 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5486 SEC_ACE_TYPE_ACCESS_ALLOWED,
5487 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5489 /* Make the security descriptor owned by the BUILTIN\Administrators */
5491 /* The ACL revision number in rpc_secdesc.h differs from the one
5492 created by NT when setting ACE entries in printer
5493 descriptors. NT4 complains about the property being edited by a
5496 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5497 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5498 &global_sid_Builtin_Administrators,
5499 &global_sid_Builtin_Administrators,
5500 NULL, psa, &sd_size);
5504 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5508 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5510 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5511 (unsigned int)sd_size));
5516 /****************************************************************************
5517 Get a security desc for a printer.
5518 ****************************************************************************/
5520 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5526 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5527 sharename = temp + 1;
5532 /* Fetch security descriptor from tdb */
5534 kbuf = make_printers_secdesc_tdbkey(ctx, sharename );
5536 if (tdb_prs_fetch(tdb_printers, kbuf, &ps, ctx)!=0 ||
5537 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5541 DEBUG(4,("using default secdesc for %s\n", sharename));
5543 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5547 /* Save default security descriptor for later */
5549 prs_init(&ps, (uint32)ndr_size_security_descriptor((*secdesc_ctr)->sd, 0) +
5550 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5552 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5553 tdb_prs_store(tdb_printers, kbuf, &ps);
5563 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5564 this security descriptor has been created when winbindd was
5565 down. Take ownership of security descriptor. */
5567 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5570 /* Change sd owner to workgroup administrator */
5572 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5573 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5574 SEC_DESC *psd = NULL;
5579 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5581 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5583 (*secdesc_ctr)->sd->group_sid,
5584 (*secdesc_ctr)->sd->sacl,
5585 (*secdesc_ctr)->sd->dacl,
5592 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5593 if (!new_secdesc_ctr) {
5597 /* Swap with other one */
5599 *secdesc_ctr = new_secdesc_ctr;
5603 nt_printing_setsec(sharename, *secdesc_ctr);
5607 if (DEBUGLEVEL >= 10) {
5608 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5611 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5612 sharename, the_acl->num_aces));
5614 for (i = 0; i < the_acl->num_aces; i++) {
5615 DEBUG(10, ("%s %d %d 0x%08x\n",
5616 sid_string_dbg(&the_acl->aces[i].trustee),
5617 the_acl->aces[i].type, the_acl->aces[i].flags,
5618 the_acl->aces[i].access_mask));
5627 1: level not implemented
5628 2: file doesn't exist
5629 3: can't allocate memory
5630 4: can't free memory
5631 5: non existant struct
5635 A printer and a printer driver are 2 different things.
5636 NT manages them separatelly, Samba does the same.
5637 Why ? Simply because it's easier and it makes sense !
5639 Now explanation: You have 3 printers behind your samba server,
5640 2 of them are the same make and model (laser A and B). But laser B
5641 has an 3000 sheet feeder and laser A doesn't such an option.
5642 Your third printer is an old dot-matrix model for the accounting :-).
5644 If the /usr/local/samba/lib directory (default dir), you will have
5645 5 files to describe all of this.
5647 3 files for the printers (1 by printer):
5650 NTprinter_accounting
5651 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5652 NTdriver_printer model X
5653 NTdriver_printer model Y
5655 jfm: I should use this comment for the text file to explain
5656 same thing for the forms BTW.
5657 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5661 /* Convert generic access rights to printer object specific access rights.
5662 It turns out that NT4 security descriptors use generic access rights and
5663 NT5 the object specific ones. */
5665 void map_printer_permissions(SEC_DESC *sd)
5669 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5670 se_map_generic(&sd->dacl->aces[i].access_mask,
5671 &printer_generic_mapping);
5675 /****************************************************************************
5676 Check a user has permissions to perform the given operation. We use the
5677 permission constants defined in include/rpc_spoolss.h to check the various
5678 actions we perform when checking printer access.
5680 PRINTER_ACCESS_ADMINISTER:
5681 print_queue_pause, print_queue_resume, update_printer_sec,
5682 update_printer, spoolss_addprinterex_level_2,
5683 _spoolss_setprinterdata
5688 JOB_ACCESS_ADMINISTER:
5689 print_job_delete, print_job_pause, print_job_resume,
5692 Try access control in the following order (for performance reasons):
5693 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5694 2) check security descriptor (bit comparisons in memory)
5695 3) "printer admins" (may result in numerous calls to winbind)
5697 ****************************************************************************/
5698 bool print_access_check(struct current_user *user, int snum, int access_type)
5700 SEC_DESC_BUF *secdesc = NULL;
5701 uint32 access_granted;
5705 TALLOC_CTX *mem_ctx = NULL;
5706 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5708 /* If user is NULL then use the current_user structure */
5711 user = ¤t_user;
5713 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5715 if ( user->ut.uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5719 /* Get printer name */
5721 pname = PRINTERNAME(snum);
5723 if (!pname || !*pname) {
5728 /* Get printer security descriptor */
5730 if(!(mem_ctx = talloc_init("print_access_check"))) {
5735 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5736 talloc_destroy(mem_ctx);
5741 if (access_type == JOB_ACCESS_ADMINISTER) {
5742 SEC_DESC_BUF *parent_secdesc = secdesc;
5744 /* Create a child security descriptor to check permissions
5745 against. This is because print jobs are child objects
5746 objects of a printer. */
5748 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sd, False);
5751 talloc_destroy(mem_ctx);
5756 /* Now this is the bit that really confuses me. The access
5757 type needs to be changed from JOB_ACCESS_ADMINISTER to
5758 PRINTER_ACCESS_ADMINISTER for this to work. Something
5759 to do with the child (job) object becoming like a
5762 access_type = PRINTER_ACCESS_ADMINISTER;
5767 map_printer_permissions(secdesc->sd);
5769 result = se_access_check(secdesc->sd, user->nt_user_token, access_type,
5770 &access_granted, &status);
5772 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5774 /* see if we need to try the printer admin list */
5776 if ((access_granted == 0) &&
5777 (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
5778 user->nt_user_token,
5779 lp_printer_admin(snum)))) {
5780 talloc_destroy(mem_ctx);
5784 talloc_destroy(mem_ctx);
5793 /****************************************************************************
5794 Check the time parameters allow a print operation.
5795 *****************************************************************************/
5797 bool print_time_access_check(const char *servicename)
5799 NT_PRINTER_INFO_LEVEL *printer = NULL;
5801 time_t now = time(NULL);
5805 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5808 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5812 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5814 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5817 free_a_printer(&printer, 2);
5825 /****************************************************************************
5826 Fill in the servername sent in the _spoolss_open_printer_ex() call
5827 ****************************************************************************/
5829 char* get_server_name( Printer_entry *printer )
5831 return printer->servername;