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/>.
23 #include "librpc/gen_ndr/messaging.h"
24 #include "printing/pcap.h"
27 static TDB_CONTEXT *tdb_forms; /* used for forms files */
28 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29 static TDB_CONTEXT *tdb_printers; /* used for printers files */
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define 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 /* Map generic permissions to job object specific permissions */
77 const struct generic_mapping job_generic_mapping = {
84 /* We need one default form to support our default printer. Msoft adds the
85 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
86 array index). Letter is always first, so (for the current code) additions
87 always put things in the correct order. */
88 static const nt_forms_struct default_forms[] = {
89 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
90 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
91 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
92 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
93 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
94 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
95 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
96 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
97 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
98 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
99 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
100 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
101 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
102 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
103 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
104 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
105 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
106 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
107 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
108 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
109 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
110 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
111 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
112 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
113 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
114 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
115 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
116 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
117 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
118 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
119 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
120 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
121 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
122 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
123 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
124 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
125 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
126 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
127 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
128 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
129 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
130 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
131 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
132 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
133 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
134 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
135 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
136 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
137 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
138 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
139 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
140 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
141 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
142 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
143 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
144 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
145 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
146 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
147 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
148 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
149 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
150 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
151 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
152 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
153 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
154 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
155 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
156 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
157 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
158 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
159 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
160 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
161 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
162 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
163 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
164 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
165 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
166 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
167 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
168 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
169 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
170 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
171 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
172 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
173 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
174 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
175 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
176 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
177 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
178 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
179 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
180 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
181 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
182 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
183 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
184 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
185 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
186 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
187 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
188 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
189 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
190 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
191 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
192 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
193 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
194 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
195 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
196 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
197 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
198 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
199 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
200 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
201 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
202 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
203 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
204 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
205 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
206 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
209 static const struct print_architecture_table_node archi_table[]= {
211 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
212 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
213 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
214 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
215 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
216 {"Windows IA64", SPL_ARCH_IA64, 3 },
217 {"Windows x64", SPL_ARCH_X64, 3 },
222 /****************************************************************************
223 generate a new TDB_DATA key for storing a printer
224 ****************************************************************************/
226 static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
232 fstrcpy(share, sharename);
235 keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
236 key = string_term_tdb_data(keystr ? keystr : "");
241 /****************************************************************************
242 generate a new TDB_DATA key for storing a printer security descriptor
243 ****************************************************************************/
245 static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
246 const char* sharename )
252 fstrcpy(share, sharename );
255 keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
256 key = string_term_tdb_data(keystr ? keystr : "");
261 /****************************************************************************
262 ****************************************************************************/
264 static bool upgrade_to_version_3(void)
266 TDB_DATA kbuf, newkey, dbuf;
268 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
270 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
271 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
273 dbuf = tdb_fetch(tdb_drivers, kbuf);
275 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
276 DEBUG(0,("upgrade_to_version_3:moving form\n"));
277 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
278 SAFE_FREE(dbuf.dptr);
279 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
282 if (tdb_delete(tdb_drivers, kbuf) != 0) {
283 SAFE_FREE(dbuf.dptr);
284 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
289 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
290 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
291 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
292 SAFE_FREE(dbuf.dptr);
293 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
296 if (tdb_delete(tdb_drivers, kbuf) != 0) {
297 SAFE_FREE(dbuf.dptr);
298 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
303 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
304 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
305 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
306 SAFE_FREE(dbuf.dptr);
307 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
310 if (tdb_delete(tdb_drivers, kbuf) != 0) {
311 SAFE_FREE(dbuf.dptr);
312 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
317 SAFE_FREE(dbuf.dptr);
323 /*******************************************************************
324 Fix an issue with security descriptors. Printer sec_desc must
325 use more than the generic bits that were previously used
326 in <= 3.0.14a. They must also have a owner and group SID assigned.
327 Otherwise, any printers than have been migrated to a Windows
328 host using printmig.exe will not be accessible.
329 *******************************************************************/
331 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
332 TDB_DATA data, void *state )
335 struct sec_desc_buf *sd_orig = NULL;
336 struct sec_desc_buf *sd_new, *sd_store;
337 struct security_descriptor *sec, *new_sec;
338 TALLOC_CTX *ctx = state;
343 if (!data.dptr || data.dsize == 0) {
347 if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
351 /* upgrade the security descriptor */
353 status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
354 if (!NT_STATUS_IS_OK(status)) {
355 /* delete bad entries */
356 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
357 (const char *)key.dptr ));
358 tdb_delete( tdb_printers, key );
367 /* is this even valid? */
373 /* update access masks */
375 for ( i=0; i<sec->dacl->num_aces; i++ ) {
376 switch ( sec->dacl->aces[i].access_mask ) {
377 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
378 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
381 case GENERIC_ALL_ACCESS:
382 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
385 case READ_CONTROL_ACCESS:
386 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
388 default: /* no change */
393 /* create a new struct security_descriptor with the appropriate owner and group SIDs */
395 new_sec = make_sec_desc( ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
396 &global_sid_Builtin_Administrators,
397 &global_sid_Builtin_Administrators,
398 NULL, NULL, &size_new_sec );
402 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
407 if ( !(sd_store = sec_desc_merge_buf( ctx, sd_new, sd_orig )) ) {
408 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
414 sd_size = ndr_size_security_descriptor(sd_store->sd, 0)
415 + sizeof(struct sec_desc_buf);
417 status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
418 if (!NT_STATUS_IS_OK(status)) {
419 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
423 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
425 /* 0 to continue and non-zero to stop traversal */
427 return (result == -1);
430 /*******************************************************************
431 *******************************************************************/
433 static bool upgrade_to_version_4(void)
438 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
440 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
443 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
445 talloc_destroy( ctx );
447 return ( result != -1 );
450 /*******************************************************************
451 Fix an issue with security descriptors. Printer sec_desc must
452 use more than the generic bits that were previously used
453 in <= 3.0.14a. They must also have a owner and group SID assigned.
454 Otherwise, any printers than have been migrated to a Windows
455 host using printmig.exe will not be accessible.
456 *******************************************************************/
458 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
459 TDB_DATA data, void *state )
461 TALLOC_CTX *ctx = talloc_tos();
464 if (!data.dptr || data.dsize == 0)
467 /* upgrade printer records and security descriptors */
469 if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
470 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
472 else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
473 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
476 /* ignore this record */
480 /* delete the original record and store under the normalized key */
482 if ( tdb_delete( the_tdb, key ) != 0 ) {
483 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
488 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
489 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
497 /*******************************************************************
498 *******************************************************************/
500 static bool upgrade_to_version_5(void)
505 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
507 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
510 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
512 talloc_destroy( ctx );
514 return ( result != -1 );
517 /****************************************************************************
518 Open the NT printing tdbs. Done once before fork().
519 ****************************************************************************/
521 bool nt_printing_init(struct messaging_context *msg_ctx)
523 const char *vstring = "INFO/version";
527 if ( tdb_drivers && tdb_printers && tdb_forms )
531 tdb_close(tdb_drivers);
532 tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
534 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
535 state_path("ntdrivers.tdb"), strerror(errno) ));
540 tdb_close(tdb_printers);
541 tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
543 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
544 state_path("ntprinters.tdb"), strerror(errno) ));
549 tdb_close(tdb_forms);
550 tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
552 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
553 state_path("ntforms.tdb"), strerror(errno) ));
557 /* handle a Samba upgrade */
559 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
561 DEBUG(10, ("Fresh database\n"));
562 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
563 vers_id = NTDRIVERS_DATABASE_VERSION_5;
566 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
568 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
569 if (!upgrade_to_version_3())
571 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
572 vers_id = NTDRIVERS_DATABASE_VERSION_3;
575 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
576 /* Written on a bigendian machine with old fetch_int code. Save as le. */
577 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
578 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
579 vers_id = NTDRIVERS_DATABASE_VERSION_3;
582 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
583 if ( !upgrade_to_version_4() )
585 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
586 vers_id = NTDRIVERS_DATABASE_VERSION_4;
589 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
590 if ( !upgrade_to_version_5() )
592 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
593 vers_id = NTDRIVERS_DATABASE_VERSION_5;
597 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
598 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
603 update_c_setprinter(True);
606 * register callback to handle updating printers as new
607 * drivers are installed
610 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
611 do_drv_upgrade_printer);
613 /* of course, none of the message callbacks matter if you don't
614 tell messages.c that you interested in receiving PRINT_GENERAL
615 msgs. This is done in serverid_register() */
618 if ( lp_security() == SEC_ADS ) {
619 win_rc = check_published_printers();
620 if (!W_ERROR_IS_OK(win_rc))
621 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
627 /*******************************************************************
628 Function to allow filename parsing "the old way".
629 ********************************************************************/
631 static NTSTATUS driver_unix_convert(connection_struct *conn,
632 const char *old_name,
633 struct smb_filename **smb_fname)
636 TALLOC_CTX *ctx = talloc_tos();
637 char *name = talloc_strdup(ctx, old_name);
640 return NT_STATUS_NO_MEMORY;
643 name = unix_clean_name(ctx, name);
645 return NT_STATUS_NO_MEMORY;
647 trim_string(name,"/","/");
649 status = unix_convert(ctx, conn, name, smb_fname, 0);
650 if (!NT_STATUS_IS_OK(status)) {
651 return NT_STATUS_NO_MEMORY;
657 /*******************************************************************
658 tdb traversal function for counting printers.
659 ********************************************************************/
661 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
662 TDB_DATA data, void *context)
664 int *printer_count = (int*)context;
666 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
668 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
674 /*******************************************************************
675 Update the spooler global c_setprinter. This variable is initialized
676 when the parent smbd starts with the number of existing printers. It
677 is monotonically increased by the current number of printers *after*
678 each add or delete printer RPC. Only Microsoft knows why... JRR020119
679 ********************************************************************/
681 uint32 update_c_setprinter(bool initialize)
684 int32 printer_count = 0;
686 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
688 /* Traverse the tdb, counting the printers */
689 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
691 /* If initializing, set c_setprinter to current printers count
692 * otherwise, bump it by the current printer count
695 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
697 c_setprinter = printer_count;
699 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
700 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
702 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
704 return (uint32)c_setprinter;
707 /*******************************************************************
708 Get the spooler global c_setprinter, accounting for initialization.
709 ********************************************************************/
711 uint32 get_c_setprinter(void)
713 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
715 if (c_setprinter == (int32)-1)
716 c_setprinter = update_c_setprinter(True);
718 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
720 return (uint32)c_setprinter;
723 /****************************************************************************
724 Get builtin form struct list.
725 ****************************************************************************/
727 int get_builtin_ntforms(nt_forms_struct **list)
729 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
733 return ARRAY_SIZE(default_forms);
736 /****************************************************************************
737 get a builtin form struct
738 ****************************************************************************/
740 bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
743 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
744 for (i=0; i<ARRAY_SIZE(default_forms); i++) {
745 if (strequal(form_name,default_forms[i].name)) {
746 DEBUGADD(6,("Found builtin form %s \n", form_name));
747 memcpy(form,&default_forms[i],sizeof(*form));
755 /****************************************************************************
756 get a form struct list.
757 ****************************************************************************/
759 int get_ntforms(nt_forms_struct **list)
761 TDB_DATA kbuf, newkey, dbuf;
762 nt_forms_struct form;
769 for (kbuf = tdb_firstkey(tdb_forms);
771 newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
773 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
776 dbuf = tdb_fetch(tdb_forms, kbuf);
780 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
781 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
782 &i, &form.flag, &form.width, &form.length, &form.left,
783 &form.top, &form.right, &form.bottom);
784 SAFE_FREE(dbuf.dptr);
785 if (ret != dbuf.dsize)
788 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
790 DEBUG(0,("get_ntforms: Realloc fail.\n"));
801 /****************************************************************************
802 write a form struct list
803 ****************************************************************************/
805 int write_ntforms(nt_forms_struct **list, int number)
807 TALLOC_CTX *ctx = talloc_tos();
814 for (i=0;i<number;i++) {
815 /* save index, so list is rebuilt in correct order */
816 len = tdb_pack(NULL, 0, "dddddddd",
817 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
818 (*list)[i].left, (*list)[i].top, (*list)[i].right,
823 buf = TALLOC_ARRAY(ctx, char, len);
827 len = tdb_pack((uint8 *)buf, len, "dddddddd",
828 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
829 (*list)[i].left, (*list)[i].top, (*list)[i].right,
831 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
836 dbuf.dptr = (uint8 *)buf;
837 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
849 /****************************************************************************
850 add a form struct at the end of the list
851 ****************************************************************************/
852 bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count)
858 * NT tries to add forms even when
859 * they are already in the base
860 * only update the values if already present
865 for (n=0; n<*count; n++) {
866 if ( strequal((*list)[n].name, form->form_name) ) {
873 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
874 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
877 fstrcpy((*list)[n].name, form->form_name);
881 (*list)[n].flag = form->flags;
882 (*list)[n].width = form->size.width;
883 (*list)[n].length = form->size.height;
884 (*list)[n].left = form->area.left;
885 (*list)[n].top = form->area.top;
886 (*list)[n].right = form->area.right;
887 (*list)[n].bottom = form->area.bottom;
889 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
890 update ? "updated" : "added", form->form_name));
895 /****************************************************************************
896 Delete a named form struct.
897 ****************************************************************************/
899 bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
906 for (n=0; n<*count; n++) {
907 if (!strncmp((*list)[n].name, del_name, strlen(del_name))) {
908 DEBUG(103, ("delete_a_form, [%s] in list\n", del_name));
914 DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
915 *ret = WERR_INVALID_FORM_NAME;
919 if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
923 if (tdb_delete_bystring(tdb_forms, key) != 0) {
932 /****************************************************************************
933 Update a form struct.
934 ****************************************************************************/
936 void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
940 DEBUG(106, ("[%s]\n", form->form_name));
941 for (n=0; n<count; n++) {
942 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
943 if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name)))
947 if (n==count) return;
949 (*list)[n].flag = form->flags;
950 (*list)[n].width = form->size.width;
951 (*list)[n].length = form->size.height;
952 (*list)[n].left = form->area.left;
953 (*list)[n].top = form->area.top;
954 (*list)[n].right = form->area.right;
955 (*list)[n].bottom = form->area.bottom;
958 /****************************************************************************
959 Get the nt drivers list.
960 Traverse the database and look-up the matching names.
961 ****************************************************************************/
962 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
965 const char *short_archi;
967 TDB_DATA kbuf, newkey;
969 short_archi = get_short_archi(architecture);
974 if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
975 short_archi, version) < 0) {
979 for (kbuf = tdb_firstkey(tdb_drivers);
981 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
983 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
986 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
987 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
992 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
1000 /****************************************************************************
1001 Function to do the mapping between the long architecture name and
1003 ****************************************************************************/
1005 const char *get_short_archi(const char *long_archi)
1009 DEBUG(107,("Getting architecture dependant directory\n"));
1012 } while ( (archi_table[i].long_archi!=NULL ) &&
1013 StrCaseCmp(long_archi, archi_table[i].long_archi) );
1015 if (archi_table[i].long_archi==NULL) {
1016 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1020 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1022 DEBUGADD(108,("index: [%d]\n", i));
1023 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1024 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1026 return archi_table[i].short_archi;
1029 /****************************************************************************
1030 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1031 There are two case to be covered here: PE (Portable Executable) and NE (New
1032 Executable) files. Both files support the same INFO structure, but PE files
1033 store the signature in unicode, and NE files store it as !unicode.
1034 returns -1 on error, 1 on version info found, and 0 on no version info found.
1035 ****************************************************************************/
1037 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1043 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1044 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1045 fname, DOS_HEADER_SIZE));
1049 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1050 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1051 fname, (unsigned long)byte_count));
1052 goto no_version_info;
1055 /* Is this really a DOS header? */
1056 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1057 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1058 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1059 goto no_version_info;
1062 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1063 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1064 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1066 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1067 goto no_version_info;
1070 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1071 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1072 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1073 fname, (unsigned long)byte_count));
1074 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1075 goto no_version_info;
1078 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1079 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1080 unsigned int num_sections;
1081 unsigned int section_table_bytes;
1083 /* Just skip over optional header to get to section table */
1084 if (SMB_VFS_LSEEK(fsp,
1085 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1086 SEEK_CUR) == (SMB_OFF_T)-1) {
1087 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1092 /* get the section table */
1093 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1094 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1095 if (section_table_bytes == 0)
1099 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1100 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1101 fname, section_table_bytes));
1105 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1106 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1107 fname, (unsigned long)byte_count));
1111 /* Iterate the section table looking for the resource section ".rsrc" */
1112 for (i = 0; i < num_sections; i++) {
1113 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1115 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1116 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1117 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1119 if (section_bytes == 0)
1123 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1124 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1125 fname, section_bytes));
1129 /* Seek to the start of the .rsrc section info */
1130 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1131 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1136 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1137 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1138 fname, (unsigned long)byte_count));
1142 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1145 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1146 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1147 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1148 /* Align to next long address */
1149 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1151 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1152 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1153 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1155 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1156 fname, *major, *minor,
1157 (*major>>16)&0xffff, *major&0xffff,
1158 (*minor>>16)&0xffff, *minor&0xffff));
1167 /* Version info not found, fall back to origin date/time */
1168 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1172 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1173 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1174 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1175 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1176 /* At this point, we assume the file is in error. It still could be somthing
1177 * else besides a NE file, but it unlikely at this point. */
1181 /* Allocate a bit more space to speed up things */
1183 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1184 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1185 fname, PE_HEADER_SIZE));
1189 /* This is a HACK! I got tired of trying to sort through the messy
1190 * 'NE' file format. If anyone wants to clean this up please have at
1191 * it, but this works. 'NE' files will eventually fade away. JRR */
1192 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1193 /* Cover case that should not occur in a well formed 'NE' .dll file */
1194 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1196 for(i=0; i<byte_count; i++) {
1197 /* Fast skip past data that can't possibly match */
1198 if (buf[i] != 'V') continue;
1200 /* Potential match data crosses buf boundry, move it to beginning
1201 * of buf, and fill the buf with as much as it will hold. */
1202 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1205 memcpy(buf, &buf[i], byte_count-i);
1206 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1207 (byte_count-i))) < 0) {
1209 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1214 byte_count = bc + (byte_count - i);
1215 if (byte_count<VS_VERSION_INFO_SIZE) break;
1220 /* Check that the full signature string and the magic number that
1221 * follows exist (not a perfect solution, but the chances that this
1222 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1223 * twice, as it is simpler to read the code. */
1224 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1225 /* Compute skip alignment to next long address */
1226 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1227 sizeof(VS_SIGNATURE)) & 3;
1228 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1230 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1231 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1232 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1233 fname, *major, *minor,
1234 (*major>>16)&0xffff, *major&0xffff,
1235 (*minor>>16)&0xffff, *minor&0xffff));
1242 /* Version info not found, fall back to origin date/time */
1243 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1248 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1249 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1250 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1261 /****************************************************************************
1262 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1263 share one or more files. During the MS installation process files are checked
1264 to insure that only a newer version of a shared file is installed over an
1265 older version. There are several possibilities for this comparison. If there
1266 is no previous version, the new one is newer (obviously). If either file is
1267 missing the version info structure, compare the creation date (on Unix use
1268 the modification date). Otherwise chose the numerically larger version number.
1269 ****************************************************************************/
1271 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1273 bool use_version = true;
1277 time_t new_create_time;
1281 time_t old_create_time;
1283 struct smb_filename *smb_fname = NULL;
1284 files_struct *fsp = NULL;
1290 SET_STAT_INVALID(st);
1291 new_create_time = (time_t)0;
1292 old_create_time = (time_t)0;
1294 /* Get file version info (if available) for previous file (if it exists) */
1295 status = driver_unix_convert(conn, old_file, &smb_fname);
1296 if (!NT_STATUS_IS_OK(status)) {
1300 status = SMB_VFS_CREATE_FILE(
1303 0, /* root_dir_fid */
1304 smb_fname, /* fname */
1305 FILE_GENERIC_READ, /* access_mask */
1306 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1307 FILE_OPEN, /* create_disposition*/
1308 0, /* create_options */
1309 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1310 INTERNAL_OPEN_ONLY, /* oplock_request */
1311 0, /* allocation_size */
1312 0, /* private_flags */
1318 if (!NT_STATUS_IS_OK(status)) {
1319 /* Old file not found, so by definition new file is in fact newer */
1320 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
1321 "errno = %d\n", smb_fname_str_dbg(smb_fname),
1327 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1333 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1335 use_version = false;
1336 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1339 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1340 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1341 (long)old_create_time));
1344 close_file(NULL, fsp, NORMAL_CLOSE);
1347 /* Get file version info (if available) for new file */
1348 status = driver_unix_convert(conn, new_file, &smb_fname);
1349 if (!NT_STATUS_IS_OK(status)) {
1353 status = SMB_VFS_CREATE_FILE(
1356 0, /* root_dir_fid */
1357 smb_fname, /* fname */
1358 FILE_GENERIC_READ, /* access_mask */
1359 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1360 FILE_OPEN, /* create_disposition*/
1361 0, /* create_options */
1362 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1363 INTERNAL_OPEN_ONLY, /* oplock_request */
1364 0, /* allocation_size */
1365 0, /* private_flags */
1371 if (!NT_STATUS_IS_OK(status)) {
1372 /* New file not found, this shouldn't occur if the caller did its job */
1373 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
1374 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
1378 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1384 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1386 use_version = false;
1387 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1390 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1391 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1392 (long)new_create_time));
1395 close_file(NULL, fsp, NORMAL_CLOSE);
1398 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1399 /* Compare versions and choose the larger version number */
1400 if (new_major > old_major ||
1401 (new_major == old_major && new_minor > old_minor)) {
1403 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1408 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1414 /* Compare modification time/dates and choose the newest time/date */
1415 if (new_create_time > old_create_time) {
1416 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));
1429 close_file(NULL, fsp, NORMAL_CLOSE);
1432 TALLOC_FREE(smb_fname);
1436 /****************************************************************************
1437 Determine the correct cVersion associated with an architecture and driver
1438 ****************************************************************************/
1439 static uint32 get_correct_cversion(struct pipes_struct *p,
1440 const char *architecture,
1441 const char *driverpath_in,
1446 struct smb_filename *smb_fname = NULL;
1447 char *driverpath = NULL;
1448 files_struct *fsp = NULL;
1449 connection_struct *conn = NULL;
1452 fstring printdollar;
1453 int printdollar_snum;
1455 *perr = WERR_INVALID_PARAM;
1457 /* If architecture is Windows 95/98/ME, the version is always 0. */
1458 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1459 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1464 /* If architecture is Windows x64, the version is always 3. */
1465 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1466 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1471 fstrcpy(printdollar, "print$");
1473 printdollar_snum = find_service(printdollar);
1474 if (printdollar_snum == -1) {
1475 *perr = WERR_NO_SUCH_SHARE;
1479 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1480 lp_pathname(printdollar_snum),
1481 p->server_info, &oldcwd);
1482 if (!NT_STATUS_IS_OK(nt_status)) {
1483 DEBUG(0,("get_correct_cversion: create_conn_struct "
1484 "returned %s\n", nt_errstr(nt_status)));
1485 *perr = ntstatus_to_werror(nt_status);
1489 /* Open the driver file (Portable Executable format) and determine the
1490 * deriver the cversion. */
1491 driverpath = talloc_asprintf(talloc_tos(),
1500 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
1501 if (!NT_STATUS_IS_OK(nt_status)) {
1502 *perr = ntstatus_to_werror(nt_status);
1506 nt_status = vfs_file_exist(conn, smb_fname);
1507 if (!NT_STATUS_IS_OK(nt_status)) {
1508 *perr = WERR_BADFILE;
1512 status = SMB_VFS_CREATE_FILE(
1515 0, /* root_dir_fid */
1516 smb_fname, /* fname */
1517 FILE_GENERIC_READ, /* access_mask */
1518 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1519 FILE_OPEN, /* create_disposition*/
1520 0, /* create_options */
1521 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1522 INTERNAL_OPEN_ONLY, /* oplock_request */
1523 0, /* private_flags */
1524 0, /* allocation_size */
1530 if (!NT_STATUS_IS_OK(status)) {
1531 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1532 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1533 *perr = WERR_ACCESS_DENIED;
1540 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1541 if (ret == -1) goto error_exit;
1544 DEBUG(6,("get_correct_cversion: Version info not "
1546 smb_fname_str_dbg(smb_fname)));
1551 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1552 * for more details. Version in this case is not just the version of the
1553 * file, but the version in the sense of kernal mode (2) vs. user mode
1554 * (3) drivers. Other bits of the version fields are the version info.
1557 cversion = major & 0x0000ffff;
1559 case 2: /* WinNT drivers */
1560 case 3: /* Win2K drivers */
1564 DEBUG(6,("get_correct_cversion: cversion "
1565 "invalid [%s] cversion = %d\n",
1566 smb_fname_str_dbg(smb_fname),
1571 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1572 " = 0x%x minor = 0x%x\n",
1573 smb_fname_str_dbg(smb_fname), major, minor));
1576 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1577 smb_fname_str_dbg(smb_fname), cversion));
1584 TALLOC_FREE(smb_fname);
1586 close_file(NULL, fsp, NORMAL_CLOSE);
1589 vfs_ChDir(conn, oldcwd);
1592 if (cversion != -1) {
1598 /****************************************************************************
1599 ****************************************************************************/
1601 #define strip_driver_path(_mem_ctx, _element) do { \
1602 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1603 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1604 W_ERROR_HAVE_NO_MEMORY((_element)); \
1608 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1609 struct pipes_struct *rpc_pipe,
1610 const char *architecture,
1611 const char **driver_path,
1612 const char **data_file,
1613 const char **config_file,
1614 const char **help_file,
1615 struct spoolss_StringArray *dependent_files,
1618 const char *short_architecture;
1623 if (!*driver_path || !*data_file || !*config_file) {
1624 return WERR_INVALID_PARAM;
1627 /* clean up the driver name.
1628 * we can get .\driver.dll
1629 * or worse c:\windows\system\driver.dll !
1631 /* using an intermediate string to not have overlaping memcpy()'s */
1633 strip_driver_path(mem_ctx, *driver_path);
1634 strip_driver_path(mem_ctx, *data_file);
1635 strip_driver_path(mem_ctx, *config_file);
1637 strip_driver_path(mem_ctx, *help_file);
1640 if (dependent_files && dependent_files->string) {
1641 for (i=0; dependent_files->string[i]; i++) {
1642 strip_driver_path(mem_ctx, dependent_files->string[i]);
1646 short_architecture = get_short_archi(architecture);
1647 if (!short_architecture) {
1648 return WERR_UNKNOWN_PRINTER_DRIVER;
1651 /* jfm:7/16/2000 the client always sends the cversion=0.
1652 * The server should check which version the driver is by reading
1653 * the PE header of driver->driverpath.
1655 * For Windows 95/98 the version is 0 (so the value sent is correct)
1656 * For Windows NT (the architecture doesn't matter)
1657 * NT 3.1: cversion=0
1658 * NT 3.5/3.51: cversion=1
1663 *version = get_correct_cversion(rpc_pipe, short_architecture,
1664 *driver_path, &err);
1665 if (*version == -1) {
1672 /****************************************************************************
1673 ****************************************************************************/
1675 WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe,
1676 struct spoolss_AddDriverInfoCtr *r)
1680 return clean_up_driver_struct_level(r, rpc_pipe,
1681 r->info.info3->architecture,
1682 &r->info.info3->driver_path,
1683 &r->info.info3->data_file,
1684 &r->info.info3->config_file,
1685 &r->info.info3->help_file,
1686 r->info.info3->dependent_files,
1687 &r->info.info3->version);
1689 return clean_up_driver_struct_level(r, rpc_pipe,
1690 r->info.info6->architecture,
1691 &r->info.info6->driver_path,
1692 &r->info.info6->data_file,
1693 &r->info.info6->config_file,
1694 &r->info.info6->help_file,
1695 r->info.info6->dependent_files,
1696 &r->info.info6->version);
1698 return WERR_NOT_SUPPORTED;
1702 /****************************************************************************
1703 This function sucks and should be replaced. JRA.
1704 ****************************************************************************/
1706 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1707 const struct spoolss_AddDriverInfo6 *src)
1709 dst->version = src->version;
1711 dst->driver_name = src->driver_name;
1712 dst->architecture = src->architecture;
1713 dst->driver_path = src->driver_path;
1714 dst->data_file = src->data_file;
1715 dst->config_file = src->config_file;
1716 dst->help_file = src->help_file;
1717 dst->monitor_name = src->monitor_name;
1718 dst->default_datatype = src->default_datatype;
1719 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1720 dst->dependent_files = src->dependent_files;
1723 /****************************************************************************
1724 This function sucks and should be replaced. JRA.
1725 ****************************************************************************/
1727 static void convert_level_8_to_level3(TALLOC_CTX *mem_ctx,
1728 struct spoolss_AddDriverInfo3 *dst,
1729 const struct spoolss_DriverInfo8 *src)
1731 dst->version = src->version;
1732 dst->driver_name = src->driver_name;
1733 dst->architecture = src->architecture;
1734 dst->driver_path = src->driver_path;
1735 dst->data_file = src->data_file;
1736 dst->config_file = src->config_file;
1737 dst->help_file = src->help_file;
1738 dst->monitor_name = src->monitor_name;
1739 dst->default_datatype = src->default_datatype;
1740 if (src->dependent_files) {
1741 dst->dependent_files = talloc_zero(mem_ctx, struct spoolss_StringArray);
1742 if (!dst->dependent_files) return;
1743 dst->dependent_files->string = src->dependent_files;
1745 dst->dependent_files = NULL;
1749 /****************************************************************************
1750 ****************************************************************************/
1752 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1753 connection_struct *conn,
1754 const char *driver_file,
1755 const char *short_architecture,
1756 uint32_t driver_version,
1759 struct smb_filename *smb_fname_old = NULL;
1760 struct smb_filename *smb_fname_new = NULL;
1761 char *old_name = NULL;
1762 char *new_name = NULL;
1766 old_name = talloc_asprintf(mem_ctx, "%s/%s",
1767 short_architecture, driver_file);
1768 W_ERROR_HAVE_NO_MEMORY(old_name);
1770 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1771 short_architecture, driver_version, driver_file);
1772 if (new_name == NULL) {
1773 TALLOC_FREE(old_name);
1777 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1779 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1780 if (!NT_STATUS_IS_OK(status)) {
1785 /* Setup a synthetic smb_filename struct */
1786 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
1787 if (!smb_fname_new) {
1792 smb_fname_new->base_name = new_name;
1794 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1795 "'%s'\n", smb_fname_old->base_name,
1796 smb_fname_new->base_name));
1798 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1799 OPENX_FILE_EXISTS_TRUNCATE |
1800 OPENX_FILE_CREATE_IF_NOT_EXIST,
1803 if (!NT_STATUS_IS_OK(status)) {
1804 DEBUG(0,("move_driver_file_to_download_area: Unable "
1805 "to rename [%s] to [%s]: %s\n",
1806 smb_fname_old->base_name, new_name,
1807 nt_errstr(status)));
1808 ret = WERR_ACCESS_DENIED;
1815 TALLOC_FREE(smb_fname_old);
1816 TALLOC_FREE(smb_fname_new);
1820 WERROR move_driver_to_download_area(struct pipes_struct *p,
1821 struct spoolss_AddDriverInfoCtr *r,
1824 struct spoolss_AddDriverInfo3 *driver;
1825 struct spoolss_AddDriverInfo3 converted_driver;
1826 const char *short_architecture;
1827 struct smb_filename *smb_dname = NULL;
1828 char *new_dir = NULL;
1829 connection_struct *conn = NULL;
1832 TALLOC_CTX *ctx = talloc_tos();
1835 fstring printdollar;
1836 int printdollar_snum;
1842 driver = r->info.info3;
1845 convert_level_6_to_level3(&converted_driver, r->info.info6);
1846 driver = &converted_driver;
1849 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1850 return WERR_UNKNOWN_LEVEL;
1853 short_architecture = get_short_archi(driver->architecture);
1854 if (!short_architecture) {
1855 return WERR_UNKNOWN_PRINTER_DRIVER;
1858 fstrcpy(printdollar, "print$");
1860 printdollar_snum = find_service(printdollar);
1861 if (printdollar_snum == -1) {
1862 *perr = WERR_NO_SUCH_SHARE;
1863 return WERR_NO_SUCH_SHARE;
1866 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1867 lp_pathname(printdollar_snum),
1868 p->server_info, &oldcwd);
1869 if (!NT_STATUS_IS_OK(nt_status)) {
1870 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1871 "returned %s\n", nt_errstr(nt_status)));
1872 *perr = ntstatus_to_werror(nt_status);
1876 new_dir = talloc_asprintf(ctx,
1884 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1885 if (!NT_STATUS_IS_OK(nt_status)) {
1890 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1892 create_directory(conn, NULL, smb_dname);
1894 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1895 * listed for this driver which has already been moved, skip it (note:
1896 * drivers may list the same file name several times. Then check if the
1897 * file already exists in archi\version\, if so, check that the version
1898 * info (or time stamps if version info is unavailable) is newer (or the
1899 * date is later). If it is, move it to archi\version\filexxx.yyy.
1900 * Otherwise, delete the file.
1902 * If a file is not moved to archi\version\ because of an error, all the
1903 * rest of the 'unmoved' driver files are removed from archi\. If one or
1904 * more of the driver's files was already moved to archi\version\, it
1905 * potentially leaves the driver in a partially updated state. Version
1906 * trauma will most likely occur if an client attempts to use any printer
1907 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1908 * done is appropriate... later JRR
1911 DEBUG(5,("Moving files now !\n"));
1913 if (driver->driver_path && strlen(driver->driver_path)) {
1915 *perr = move_driver_file_to_download_area(ctx,
1917 driver->driver_path,
1921 if (!W_ERROR_IS_OK(*perr)) {
1922 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1929 if (driver->data_file && strlen(driver->data_file)) {
1930 if (!strequal(driver->data_file, driver->driver_path)) {
1932 *perr = move_driver_file_to_download_area(ctx,
1938 if (!W_ERROR_IS_OK(*perr)) {
1939 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1947 if (driver->config_file && strlen(driver->config_file)) {
1948 if (!strequal(driver->config_file, driver->driver_path) &&
1949 !strequal(driver->config_file, driver->data_file)) {
1951 *perr = move_driver_file_to_download_area(ctx,
1953 driver->config_file,
1957 if (!W_ERROR_IS_OK(*perr)) {
1958 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1966 if (driver->help_file && strlen(driver->help_file)) {
1967 if (!strequal(driver->help_file, driver->driver_path) &&
1968 !strequal(driver->help_file, driver->data_file) &&
1969 !strequal(driver->help_file, driver->config_file)) {
1971 *perr = move_driver_file_to_download_area(ctx,
1977 if (!W_ERROR_IS_OK(*perr)) {
1978 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1986 if (driver->dependent_files && driver->dependent_files->string) {
1987 for (i=0; driver->dependent_files->string[i]; i++) {
1988 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1989 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1990 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1991 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1993 for (j=0; j < i; j++) {
1994 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1999 *perr = move_driver_file_to_download_area(ctx,
2001 driver->dependent_files->string[i],
2005 if (!W_ERROR_IS_OK(*perr)) {
2006 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
2017 TALLOC_FREE(smb_dname);
2020 vfs_ChDir(conn, oldcwd);
2024 if (W_ERROR_EQUAL(*perr, WERR_OK)) {
2028 return WERR_UNKNOWN_PRINTER_DRIVER;
2033 /****************************************************************************
2034 ****************************************************************************/
2036 static uint32 add_a_printer_driver_3(struct spoolss_AddDriverInfo3 *driver)
2038 TALLOC_CTX *ctx = talloc_tos();
2040 const char *architecture;
2041 char *directory = NULL;
2047 architecture = get_short_archi(driver->architecture);
2048 if (!architecture) {
2052 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2053 * \\server is added in the rpc server layer.
2054 * It does make sense to NOT store the server's name in the printer TDB.
2057 directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
2058 architecture, driver->version);
2063 #define gen_full_driver_unc_path(ctx, directory, file) \
2065 if (file && strlen(file)) { \
2066 file = talloc_asprintf(ctx, "%s%s", directory, file); \
2068 file = talloc_strdup(ctx, ""); \
2071 return (uint32_t)-1; \
2075 /* .inf files do not always list a file for each of the four standard files.
2076 * Don't prepend a path to a null filename, or client claims:
2077 * "The server on which the printer resides does not have a suitable
2078 * <printer driver name> printer driver installed. Click OK if you
2079 * wish to install the driver on your local machine."
2082 gen_full_driver_unc_path(ctx, directory, driver->driver_path);
2083 gen_full_driver_unc_path(ctx, directory, driver->data_file);
2084 gen_full_driver_unc_path(ctx, directory, driver->config_file);
2085 gen_full_driver_unc_path(ctx, directory, driver->help_file);
2087 if (driver->dependent_files && driver->dependent_files->string) {
2088 for (i=0; driver->dependent_files->string[i]; i++) {
2089 gen_full_driver_unc_path(ctx, directory,
2090 driver->dependent_files->string[i]);
2094 key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
2095 architecture, driver->version, driver->driver_name);
2100 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
2107 len += tdb_pack(buf+len, buflen-len, "dffffffff",
2109 driver->driver_name,
2110 driver->architecture,
2111 driver->driver_path,
2113 driver->config_file,
2115 driver->monitor_name ? driver->monitor_name : "",
2116 driver->default_datatype ? driver->default_datatype : "");
2118 if (driver->dependent_files && driver->dependent_files->string) {
2119 for (i=0; driver->dependent_files->string[i]; i++) {
2120 len += tdb_pack(buf+len, buflen-len, "f",
2121 driver->dependent_files->string[i]);
2125 if (len != buflen) {
2126 buf = (uint8 *)SMB_REALLOC(buf, len);
2128 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2139 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2143 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2149 /****************************************************************************
2150 ****************************************************************************/
2152 static uint32_t add_a_printer_driver_8(struct spoolss_DriverInfo8 *driver)
2154 TALLOC_CTX *mem_ctx = talloc_new(talloc_tos());
2155 struct spoolss_AddDriverInfo3 info3;
2158 convert_level_8_to_level3(mem_ctx, &info3, driver);
2160 ret = add_a_printer_driver_3(&info3);
2161 talloc_free(mem_ctx);
2166 /****************************************************************************
2167 ****************************************************************************/
2169 static WERROR get_a_printer_driver_3_default(TALLOC_CTX *mem_ctx,
2170 struct spoolss_DriverInfo3 *info,
2171 const char *driver, const char *arch)
2173 info->driver_name = talloc_strdup(mem_ctx, driver);
2174 if (!info->driver_name) {
2178 info->default_datatype = talloc_strdup(mem_ctx, "RAW");
2179 if (!info->default_datatype) {
2183 info->driver_path = talloc_strdup(mem_ctx, "");
2184 info->data_file = talloc_strdup(mem_ctx, "");
2185 info->config_file = talloc_strdup(mem_ctx, "");
2186 info->help_file = talloc_strdup(mem_ctx, "");
2187 if (!info->driver_path || !info->data_file || !info->config_file || !info->help_file) {
2194 /****************************************************************************
2195 ****************************************************************************/
2197 static WERROR get_a_printer_driver_3(TALLOC_CTX *mem_ctx,
2198 struct spoolss_DriverInfo3 *driver,
2199 const char *drivername, const char *arch,
2203 const char *architecture;
2207 fstring name, driverpath, environment, datafile, configfile, helpfile, monitorname, defaultdatatype;
2209 architecture = get_short_archi(arch);
2210 if ( !architecture ) {
2211 return WERR_UNKNOWN_PRINTER_DRIVER;
2214 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2216 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2219 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2221 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
2222 architecture, version, drivername) < 0) {
2226 dbuf = tdb_fetch_bystring(tdb_drivers, key);
2229 return WERR_UNKNOWN_PRINTER_DRIVER;
2232 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2243 driver->driver_name = talloc_strdup(mem_ctx, name);
2244 driver->architecture = talloc_strdup(mem_ctx, environment);
2245 driver->driver_path = talloc_strdup(mem_ctx, driverpath);
2246 driver->data_file = talloc_strdup(mem_ctx, datafile);
2247 driver->config_file = talloc_strdup(mem_ctx, configfile);
2248 driver->help_file = talloc_strdup(mem_ctx, helpfile);
2249 driver->monitor_name = talloc_strdup(mem_ctx, monitorname);
2250 driver->default_datatype = talloc_strdup(mem_ctx, defaultdatatype);
2254 while (len < dbuf.dsize) {
2258 driver->dependent_files = talloc_realloc(mem_ctx, driver->dependent_files, const char *, i+2);
2259 if (!driver->dependent_files ) {
2260 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2264 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2267 driver->dependent_files[i] = talloc_strdup(mem_ctx, file);
2272 if (driver->dependent_files)
2273 driver->dependent_files[i] = NULL;
2275 SAFE_FREE(dbuf.dptr);
2278 if (len != dbuf.dsize) {
2279 return get_a_printer_driver_3_default(mem_ctx, driver, drivername, arch);
2285 /****************************************************************************
2286 ****************************************************************************/
2287 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2291 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2296 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2297 nt_devmode->devicename,
2298 nt_devmode->formname,
2300 nt_devmode->specversion,
2301 nt_devmode->driverversion,
2303 nt_devmode->driverextra,
2304 nt_devmode->orientation,
2305 nt_devmode->papersize,
2306 nt_devmode->paperlength,
2307 nt_devmode->paperwidth,
2310 nt_devmode->defaultsource,
2311 nt_devmode->printquality,
2314 nt_devmode->yresolution,
2315 nt_devmode->ttoption,
2316 nt_devmode->collate,
2317 nt_devmode->logpixels,
2320 nt_devmode->bitsperpel,
2321 nt_devmode->pelswidth,
2322 nt_devmode->pelsheight,
2323 nt_devmode->displayflags,
2324 nt_devmode->displayfrequency,
2325 nt_devmode->icmmethod,
2326 nt_devmode->icmintent,
2327 nt_devmode->mediatype,
2328 nt_devmode->dithertype,
2329 nt_devmode->reserved1,
2330 nt_devmode->reserved2,
2331 nt_devmode->panningwidth,
2332 nt_devmode->panningheight,
2333 nt_devmode->nt_dev_private);
2335 if (nt_devmode->nt_dev_private) {
2336 len += tdb_pack(buf+len, buflen-len, "B",
2337 nt_devmode->driverextra,
2338 nt_devmode->nt_dev_private);
2341 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2346 /****************************************************************************
2347 Pack all values in all printer keys
2348 ***************************************************************************/
2350 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2354 struct regval_blob *val;
2355 struct regval_ctr *val_ctr;
2362 /* loop over all keys */
2364 for ( i=0; i<data->num_keys; i++ ) {
2365 val_ctr = data->keys[i].values;
2366 num_values = regval_ctr_numvals( val_ctr );
2368 /* pack the keyname followed by a empty value */
2370 len += tdb_pack(buf+len, buflen-len, "pPdB",
2371 &data->keys[i].name,
2377 /* now loop over all values */
2379 for ( j=0; j<num_values; j++ ) {
2380 /* pathname should be stored as <key>\<value> */
2382 val = regval_ctr_specific_value( val_ctr, j );
2383 if (asprintf(&path, "%s\\%s",
2385 regval_name(val)) < 0) {
2389 len += tdb_pack(buf+len, buflen-len, "pPdB",
2394 regval_data_p(val) );
2396 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2404 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2410 /****************************************************************************
2411 Delete a printer - this just deletes the printer info file, any open
2412 handles are not affected.
2413 ****************************************************************************/
2415 uint32 del_a_printer(const char *sharename)
2418 char *printdb_path = NULL;
2419 TALLOC_CTX *ctx = talloc_tos();
2421 kbuf = make_printer_tdbkey(ctx, sharename);
2422 tdb_delete(tdb_printers, kbuf);
2424 kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2425 tdb_delete(tdb_printers, kbuf);
2427 close_all_print_db();
2429 if (geteuid() == sec_initial_uid()) {
2430 if (asprintf(&printdb_path, "%s%s.tdb",
2431 cache_path("printing/"),
2435 unlink(printdb_path);
2436 SAFE_FREE(printdb_path);
2442 /****************************************************************************
2443 ****************************************************************************/
2444 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2450 TDB_DATA kbuf, dbuf;
2453 * in addprinter: no servername and the printer is the name
2454 * in setprinter: servername is \\server
2455 * and printer is \\server\\printer
2457 * Samba manages only local printers.
2458 * we currently don't support things like i
2459 * path=\\other_server\printer
2461 * We only store the printername, not \\server\printername
2464 if ( info->servername[0] != '\0' ) {
2465 trim_string(info->printername, info->servername, NULL);
2466 trim_char(info->printername, '\\', '\0');
2467 info->servername[0]='\0';
2471 * JFM: one day I'll forget.
2472 * below that's info->portname because that's the SAMBA sharename
2473 * and I made NT 'thinks' it's the portname
2474 * the info->sharename is the thing you can name when you add a printer
2475 * that's the short-name when you create shared printer for 95/98
2476 * So I've made a limitation in SAMBA: you can only have 1 printer model
2477 * behind a SAMBA share.
2485 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2488 info->default_priority,
2505 info->printprocessor,
2509 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2510 retlen = pack_values( info->data, buf+len, buflen-len );
2517 if (buflen != len) {
2518 buf = (uint8 *)SMB_REALLOC(buf, len);
2520 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2528 kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2533 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2536 if (!W_ERROR_IS_OK(ret))
2537 DEBUG(8, ("error updating printer to tdb on disk\n"));
2541 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2542 info->sharename, info->drivername, info->portname, len));
2547 /****************************************************************************
2548 Create and allocate a default devicemode.
2549 ****************************************************************************/
2551 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
2552 const char *devicename,
2553 struct spoolss_DeviceMode **devmode)
2555 struct spoolss_DeviceMode *dm;
2558 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2563 dname = talloc_asprintf(dm, "%s", devicename);
2564 if (dname == NULL) {
2567 if (strlen(dname) > MAXDEVICENAME) {
2568 dname[MAXDEVICENAME] = '\0';
2570 dm->devicename = dname;
2572 dm->formname = talloc_strdup(dm, "Letter");
2573 if (dm->formname == NULL) {
2577 dm->specversion = DMSPEC_NT4_AND_ABOVE;
2578 dm->driverversion = 0x0400;
2580 dm->__driverextra_length = 0;
2581 dm->fields = DEVMODE_FORMNAME |
2583 DEVMODE_PRINTQUALITY |
2584 DEVMODE_DEFAULTSOURCE |
2588 DEVMODE_ORIENTATION;
2589 dm->orientation = DMORIENT_PORTRAIT;
2590 dm->papersize = DMPAPER_LETTER;
2591 dm->paperlength = 0;
2595 dm->defaultsource = DMBIN_FORMSOURCE;
2596 dm->printquality = DMRES_HIGH; /* 0x0258 */
2597 dm->color = DMRES_MONOCHROME;
2598 dm->duplex = DMDUP_SIMPLEX;
2599 dm->yresolution = 0;
2600 dm->ttoption = DMTT_SUBDEV;
2601 dm->collate = DMCOLLATE_FALSE;
2611 dm->displayflags = 0;
2612 dm->displayfrequency = 0;
2615 dm->panningwidth = 0;
2616 dm->panningheight = 0;
2618 dm->driverextra_data.data = NULL;
2619 dm->driverextra_data.length = 0;
2625 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
2626 struct spoolss_security_descriptor **secdesc)
2628 struct security_ace ace[5]; /* max number of ace entries */
2631 struct security_acl *psa = NULL;
2632 struct security_descriptor *psd = NULL;
2636 /* Create an ACE where Everyone is allowed to print */
2638 sa = PRINTER_ACE_PRINT;
2639 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2640 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2642 /* Add the domain admins group if we are a DC */
2645 DOM_SID domadmins_sid;
2647 sid_compose(&domadmins_sid, get_global_sam_sid(),
2650 sa = PRINTER_ACE_FULL_CONTROL;
2651 init_sec_ace(&ace[i++], &domadmins_sid,
2652 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2653 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2654 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2655 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2657 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
2658 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
2660 sa = PRINTER_ACE_FULL_CONTROL;
2661 init_sec_ace(&ace[i++], &adm_sid,
2662 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2663 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2664 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2665 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2668 /* add BUILTIN\Administrators as FULL CONTROL */
2670 sa = PRINTER_ACE_FULL_CONTROL;
2671 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2672 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2673 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2674 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2675 SEC_ACE_TYPE_ACCESS_ALLOWED,
2676 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2678 /* Make the security descriptor owned by the BUILTIN\Administrators */
2680 /* The ACL revision number in rpc_secdesc.h differs from the one
2681 created by NT when setting ACE entries in printer
2682 descriptors. NT4 complains about the property being edited by a
2685 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
2686 psd = make_sec_desc(mem_ctx,
2688 SEC_DESC_SELF_RELATIVE,
2689 &global_sid_Builtin_Administrators,
2690 &global_sid_Builtin_Administrators,
2697 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2701 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2702 (unsigned int)sd_size));
2709 /****************************************************************************
2710 Malloc and return an NT devicemode.
2711 ****************************************************************************/
2713 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2716 char adevice[MAXDEVICENAME];
2717 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2719 if (nt_devmode == NULL) {
2720 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2724 ZERO_STRUCTP(nt_devmode);
2726 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2727 fstrcpy(nt_devmode->devicename, adevice);
2729 fstrcpy(nt_devmode->formname, "Letter");
2731 nt_devmode->specversion = DMSPEC_NT4_AND_ABOVE;
2732 nt_devmode->driverversion = 0x0400;
2733 nt_devmode->size = 0x00DC;
2734 nt_devmode->driverextra = 0x0000;
2735 nt_devmode->fields = DEVMODE_FORMNAME |
2737 DEVMODE_PRINTQUALITY |
2738 DEVMODE_DEFAULTSOURCE |
2742 DEVMODE_ORIENTATION;
2743 nt_devmode->orientation = DMORIENT_PORTRAIT;
2744 nt_devmode->papersize = DMPAPER_LETTER;
2745 nt_devmode->paperlength = 0;
2746 nt_devmode->paperwidth = 0;
2747 nt_devmode->scale = 0x64;
2748 nt_devmode->copies = 1;
2749 nt_devmode->defaultsource = DMBIN_FORMSOURCE;
2750 nt_devmode->printquality = DMRES_HIGH; /* 0x0258 */
2751 nt_devmode->color = DMRES_MONOCHROME;
2752 nt_devmode->duplex = DMDUP_SIMPLEX;
2753 nt_devmode->yresolution = 0;
2754 nt_devmode->ttoption = DMTT_SUBDEV;
2755 nt_devmode->collate = DMCOLLATE_FALSE;
2756 nt_devmode->icmmethod = 0;
2757 nt_devmode->icmintent = 0;
2758 nt_devmode->mediatype = 0;
2759 nt_devmode->dithertype = 0;
2761 /* non utilisés par un driver d'imprimante */
2762 nt_devmode->logpixels = 0;
2763 nt_devmode->bitsperpel = 0;
2764 nt_devmode->pelswidth = 0;
2765 nt_devmode->pelsheight = 0;
2766 nt_devmode->displayflags = 0;
2767 nt_devmode->displayfrequency = 0;
2768 nt_devmode->reserved1 = 0;
2769 nt_devmode->reserved2 = 0;
2770 nt_devmode->panningwidth = 0;
2771 nt_devmode->panningheight = 0;
2773 nt_devmode->nt_dev_private = NULL;
2777 /****************************************************************************
2778 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2779 ****************************************************************************/
2781 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2783 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2785 if(nt_devmode == NULL)
2788 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2790 SAFE_FREE(nt_devmode->nt_dev_private);
2791 SAFE_FREE(*devmode_ptr);
2794 /****************************************************************************
2795 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2796 ****************************************************************************/
2798 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2800 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2805 free_nt_devicemode(&info->devmode);
2807 TALLOC_FREE( *info_ptr );
2811 /****************************************************************************
2812 ****************************************************************************/
2813 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2817 NT_DEVICEMODE devmode;
2819 ZERO_STRUCT(devmode);
2821 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2823 if (!*nt_devmode) return len;
2825 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2829 &devmode.specversion,
2830 &devmode.driverversion,
2832 &devmode.driverextra,
2833 &devmode.orientation,
2835 &devmode.paperlength,
2836 &devmode.paperwidth,
2839 &devmode.defaultsource,
2840 &devmode.printquality,
2843 &devmode.yresolution,
2849 &devmode.bitsperpel,
2851 &devmode.pelsheight,
2852 &devmode.displayflags,
2853 &devmode.displayfrequency,
2857 &devmode.dithertype,
2860 &devmode.panningwidth,
2861 &devmode.panningheight,
2862 &devmode.nt_dev_private);
2864 if (devmode.nt_dev_private) {
2865 /* the len in tdb_unpack is an int value and
2866 * devmode.driverextra is only a short
2868 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2869 devmode.driverextra=(uint16)extra_len;
2871 /* check to catch an invalid TDB entry so we don't segfault */
2872 if (devmode.driverextra == 0) {
2873 devmode.nt_dev_private = NULL;
2877 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2879 SAFE_FREE(devmode.nt_dev_private);
2883 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2884 if (devmode.nt_dev_private)
2885 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2890 /****************************************************************************
2891 Allocate and initialize a new slot.
2892 ***************************************************************************/
2894 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2899 if ( !name || !data )
2902 /* allocate another slot in the NT_PRINTER_KEY array */
2904 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2905 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2911 key_index = data->num_keys;
2913 /* initialze new key */
2915 data->keys[key_index].name = talloc_strdup( data, name );
2917 if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, struct regval_ctr )) )
2922 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2927 /****************************************************************************
2928 search for a registry key name in the existing printer data
2929 ***************************************************************************/
2931 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2935 for ( i=0; i<data->num_keys; i++ ) {
2936 if ( strequal( data->keys[i].name, name ) ) {
2938 /* cleanup memory */
2940 TALLOC_FREE( data->keys[i].name );
2941 TALLOC_FREE( data->keys[i].values );
2943 /* if not the end of the array, move remaining elements down one slot */
2946 if ( data->num_keys && (i < data->num_keys) )
2947 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2954 return data->num_keys;
2957 /****************************************************************************
2958 search for a registry key name in the existing printer data
2959 ***************************************************************************/
2961 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2966 if ( !data || !name )
2969 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2971 /* loop over all existing keys */
2973 for ( i=0; i<data->num_keys; i++ ) {
2974 if ( strequal(data->keys[i].name, name) ) {
2975 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2985 /****************************************************************************
2986 ***************************************************************************/
2988 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2992 int num_subkeys = 0;
2994 fstring *subkeys_ptr = NULL;
3005 /* special case of asking for the top level printer data registry key names */
3007 if ( strlen(key) == 0 ) {
3008 for ( i=0; i<data->num_keys; i++ ) {
3010 /* found a match, so allocate space and copy the name */
3012 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3013 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3018 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
3025 /* asking for the subkeys of some key */
3026 /* subkey paths are stored in the key name using '\' as the delimiter */
3028 for ( i=0; i<data->num_keys; i++ ) {
3029 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
3031 /* if we found the exact key, then break */
3032 key_len = strlen( key );
3033 if ( strlen(data->keys[i].name) == key_len )
3036 /* get subkey path */
3038 p = data->keys[i].name + key_len;
3041 fstrcpy( subkeyname, p );
3042 if ( (p = strchr( subkeyname, '\\' )) )
3045 /* don't add a key more than once */
3047 for ( j=0; j<num_subkeys; j++ ) {
3048 if ( strequal( subkeys_ptr[j], subkeyname ) )
3052 if ( j != num_subkeys )
3055 /* found a match, so allocate space and copy the name */
3057 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3058 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3063 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
3069 /* return error if the key was not found */
3071 if ( i == data->num_keys ) {
3072 SAFE_FREE(subkeys_ptr);
3077 /* tag off the end */
3080 fstrcpy(subkeys_ptr[num_subkeys], "" );
3082 *subkeys = subkeys_ptr;
3088 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3091 regval_ctr_delvalue(ctr, val_name);
3092 regval_ctr_addvalue_sz(ctr, val_name, sz);
3095 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
3098 regval_ctr_delvalue(ctr, val_name);
3099 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
3100 (char *) &dword, sizeof(dword));
3103 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
3106 uint8 bin_bool = (b ? 1 : 0);
3107 regval_ctr_delvalue(ctr, val_name);
3108 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
3109 (char *) &bin_bool, sizeof(bin_bool));
3112 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3113 const char *multi_sz)
3120 regval_ctr_delvalue(ctr, val_name);
3121 regval_ctr_addvalue_multi_sz(ctr, val_name, a);
3124 /****************************************************************************
3125 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3127 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3128 * @return bool indicating success or failure
3129 ***************************************************************************/
3131 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
3133 struct regval_ctr *ctr = NULL;
3135 const char *dnssuffix;
3136 char *allocated_string = NULL;
3137 const char *ascii_str;
3140 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3141 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3142 ctr = info2->data->keys[i].values;
3144 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3145 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3147 /* we make the assumption that the netbios name is the same
3148 as the DNS name sinc ethe former will be what we used to
3151 dnssuffix = get_mydnsdomname(talloc_tos());
3152 if (dnssuffix && *dnssuffix) {
3153 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3155 fstrcpy( longname, global_myname() );
3158 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3160 if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3163 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3164 SAFE_FREE(allocated_string);
3166 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3167 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3168 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3169 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3170 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3171 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3172 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3173 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3174 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3176 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3177 (info2->attributes &
3178 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3180 switch (info2->attributes & 0x3) {
3182 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3185 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3188 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3191 ascii_str = "unknown";
3193 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3198 /*****************************************************************
3199 ****************************************************************/
3201 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3205 struct regval_ctr *ctr=NULL;
3207 /* find the DsSpooler key */
3208 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3209 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3210 ctr = info2->data->keys[i].values;
3212 regval_ctr_delvalue(ctr, "objectGUID");
3214 /* We used to store this as a REG_BINARY but that causes
3217 regval_ctr_addvalue_sz(ctr, "objectGUID",
3218 GUID_string(talloc_tos(), &guid));
3221 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3222 NT_PRINTER_INFO_LEVEL *printer)
3226 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3227 char *srv_dn_utf8, **srv_cn_utf8;
3230 const char *attrs[] = {"objectGUID", NULL};
3232 WERROR win_rc = WERR_OK;
3233 size_t converted_size;
3235 /* build the ads mods */
3236 ctx = talloc_init("nt_printer_publish_ads");
3241 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3243 /* figure out where to publish */
3244 ads_find_machine_acct(ads, &res, global_myname());
3246 /* We use ldap_get_dn here as we need the answer
3247 * in utf8 to call ldap_explode_dn(). JRA. */
3249 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3252 return WERR_SERVER_UNAVAILABLE;
3254 ads_msgfree(ads, res);
3255 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3258 ldap_memfree(srv_dn_utf8);
3259 return WERR_SERVER_UNAVAILABLE;
3261 /* Now convert to CH_UNIX. */
3262 if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3264 ldap_memfree(srv_dn_utf8);
3265 ldap_memfree(srv_cn_utf8);
3266 return WERR_SERVER_UNAVAILABLE;
3268 if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3270 ldap_memfree(srv_dn_utf8);
3271 ldap_memfree(srv_cn_utf8);
3272 TALLOC_FREE(srv_dn);
3273 return WERR_SERVER_UNAVAILABLE;
3276 ldap_memfree(srv_dn_utf8);
3277 ldap_memfree(srv_cn_utf8);
3279 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3280 if (!srv_cn_escaped) {
3282 return WERR_SERVER_UNAVAILABLE;
3284 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3285 if (!sharename_escaped) {
3286 SAFE_FREE(srv_cn_escaped);
3288 return WERR_SERVER_UNAVAILABLE;
3291 prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3293 SAFE_FREE(srv_cn_escaped);
3294 SAFE_FREE(sharename_escaped);
3296 mods = ads_init_mods(ctx);
3304 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3305 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3306 printer->info_2->sharename);
3309 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3310 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3312 for (i=0; mods[i] != 0; i++)
3314 mods[i] = (LDAPMod *)-1;
3315 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3318 if (!ADS_ERR_OK(ads_rc))
3319 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3321 /* retreive the guid and store it locally */
3322 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3324 ads_pull_guid(ads, res, &guid);
3325 ads_msgfree(ads, res);
3326 store_printer_guid(printer->info_2, guid);
3327 win_rc = mod_a_printer(printer, 2);
3334 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3335 NT_PRINTER_INFO_LEVEL *printer)
3338 LDAPMessage *res = NULL;
3339 char *prt_dn = NULL;
3341 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3343 /* remove the printer from the directory */
3344 ads_rc = ads_find_printer_on_server(ads, &res,
3345 printer->info_2->sharename, global_myname());
3347 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3348 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3350 ads_msgfree(ads, res);
3353 ads_rc = ads_del_dn(ads, prt_dn);
3354 TALLOC_FREE(prt_dn);
3358 ads_msgfree(ads, res);
3363 /****************************************************************************
3364 * Publish a printer in the directory
3366 * @param snum describing printer service
3367 * @return WERROR indicating status of publishing
3368 ***************************************************************************/
3370 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3373 ADS_STRUCT *ads = NULL;
3374 NT_PRINTER_INFO_LEVEL *printer = NULL;
3377 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3378 if (!W_ERROR_IS_OK(win_rc))
3382 case DSPRINT_PUBLISH:
3383 case DSPRINT_UPDATE:
3384 /* set the DsSpooler info and attributes */
3385 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3386 win_rc = WERR_NOMEM;
3390 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3392 case DSPRINT_UNPUBLISH:
3393 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3396 win_rc = WERR_NOT_SUPPORTED;
3400 win_rc = mod_a_printer(printer, 2);
3401 if (!W_ERROR_IS_OK(win_rc)) {
3402 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3406 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3408 DEBUG(3, ("ads_init() failed\n"));
3409 win_rc = WERR_SERVER_UNAVAILABLE;
3412 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3413 SAFE_FREE(ads->auth.password);
3414 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3417 /* ads_connect() will find the DC for us */
3418 ads_rc = ads_connect(ads);
3419 if (!ADS_ERR_OK(ads_rc)) {
3420 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3421 win_rc = WERR_ACCESS_DENIED;
3426 case DSPRINT_PUBLISH:
3427 case DSPRINT_UPDATE:
3428 win_rc = nt_printer_publish_ads(ads, printer);
3430 case DSPRINT_UNPUBLISH:
3431 win_rc = nt_printer_unpublish_ads(ads, printer);
3436 free_a_printer(&printer, 2);
3441 WERROR check_published_printers(void)
3444 ADS_STRUCT *ads = NULL;
3446 int n_services = lp_numservices();
3447 NT_PRINTER_INFO_LEVEL *printer = NULL;
3449 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3451 DEBUG(3, ("ads_init() failed\n"));
3452 return WERR_SERVER_UNAVAILABLE;
3454 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3455 SAFE_FREE(ads->auth.password);
3456 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3459 /* ads_connect() will find the DC for us */
3460 ads_rc = ads_connect(ads);
3461 if (!ADS_ERR_OK(ads_rc)) {
3462 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3464 ads_kdestroy("MEMORY:prtpub_cache");
3465 return WERR_ACCESS_DENIED;
3468 for (snum = 0; snum < n_services; snum++) {
3469 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3472 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3473 lp_servicename(snum))) &&
3474 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3475 nt_printer_publish_ads(ads, printer);
3477 free_a_printer(&printer, 2);
3481 ads_kdestroy("MEMORY:prtpub_cache");
3485 bool is_printer_published(Printer_entry *print_hnd, int snum,
3488 NT_PRINTER_INFO_LEVEL *printer = NULL;
3489 struct regval_ctr *ctr;
3490 struct regval_blob *guid_val;
3496 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3498 if (!W_ERROR_IS_OK(win_rc) ||
3499 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3500 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3501 !(ctr = printer->info_2->data->keys[i].values) ||
3502 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3504 free_a_printer(&printer, 2);
3508 /* fetching printer guids really ought to be a separate function. */
3513 /* We used to store the guid as REG_BINARY, then swapped
3514 to REG_SZ for Vista compatibility so check for both */
3516 switch ( regval_type(guid_val) ){
3518 blob = data_blob_const(regval_data_p(guid_val),
3519 regval_size(guid_val));
3520 pull_reg_sz(talloc_tos(), &blob, (const char **)&guid_str);
3521 ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3522 talloc_free(guid_str);
3525 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3529 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3532 DEBUG(0,("is_printer_published: GUID value stored as "
3533 "invaluid type (%d)\n", regval_type(guid_val) ));
3538 free_a_printer(&printer, 2);
3542 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3547 WERROR check_published_printers(void)
3552 bool is_printer_published(Printer_entry *print_hnd, int snum,
3557 #endif /* HAVE_ADS */
3559 /****************************************************************************
3560 ***************************************************************************/
3562 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3564 NT_PRINTER_DATA *data;
3566 int removed_keys = 0;
3570 empty_slot = data->num_keys;
3573 return WERR_INVALID_PARAM;
3575 /* remove all keys */
3577 if ( !strlen(key) ) {
3579 TALLOC_FREE( data );
3583 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3589 /* remove a specific key (and all subkeys) */
3591 for ( i=0; i<data->num_keys; i++ ) {
3592 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3593 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3594 data->keys[i].name));
3596 TALLOC_FREE( data->keys[i].name );
3597 TALLOC_FREE( data->keys[i].values );
3599 /* mark the slot as empty */
3601 ZERO_STRUCTP( &data->keys[i] );
3605 /* find the first empty slot */
3607 for ( i=0; i<data->num_keys; i++ ) {
3608 if ( !data->keys[i].name ) {
3615 if ( i == data->num_keys )
3616 /* nothing was removed */
3617 return WERR_INVALID_PARAM;
3619 /* move everything down */
3621 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3622 if ( data->keys[i].name ) {
3623 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3624 ZERO_STRUCTP( &data->keys[i] );
3632 data->num_keys -= removed_keys;
3634 /* sanity check to see if anything is left */
3636 if ( !data->num_keys ) {
3637 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3639 SAFE_FREE( data->keys );
3640 ZERO_STRUCTP( data );
3646 /****************************************************************************
3647 ***************************************************************************/
3649 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3651 WERROR result = WERR_OK;
3654 /* we must have names on non-zero length */
3656 if ( !key || !*key|| !value || !*value )
3657 return WERR_INVALID_NAME;
3659 /* find the printer key first */
3661 key_index = lookup_printerkey( p2->data, key );
3662 if ( key_index == -1 )
3665 /* make sure the value exists so we can return the correct error code */
3667 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3668 return WERR_BADFILE;
3670 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3672 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3678 /****************************************************************************
3679 ***************************************************************************/
3681 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3682 uint32 type, uint8 *data, int real_len )
3684 WERROR result = WERR_OK;
3687 /* we must have names on non-zero length */
3689 if ( !key || !*key|| !value || !*value )
3690 return WERR_INVALID_NAME;
3692 /* find the printer key first */
3694 key_index = lookup_printerkey( p2->data, key );
3695 if ( key_index == -1 )
3696 key_index = add_new_printer_key( p2->data, key );
3698 if ( key_index == -1 )
3701 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3702 type, (const char *)data, real_len );
3704 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3705 key, value, type, real_len ));
3710 /****************************************************************************
3711 ***************************************************************************/
3713 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3717 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3720 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3723 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3726 /****************************************************************************
3727 Unpack a list of registry values frem the TDB
3728 ***************************************************************************/
3730 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3735 const char *valuename = NULL;
3736 const char *keyname = NULL;
3740 struct regval_blob *regval_p;
3743 /* add the "PrinterDriverData" key first for performance reasons */
3745 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3747 /* loop and unpack the rest of the registry values */
3751 /* check to see if there are any more registry values */
3754 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3758 /* unpack the next regval */
3760 len += tdb_unpack(buf+len, buflen-len, "fdB",
3766 /* lookup for subkey names which have a type of REG_NONE */
3767 /* there's no data with this entry */
3769 if ( type == REG_NONE ) {
3770 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3771 add_new_printer_key( printer_data, string );
3776 * break of the keyname from the value name.
3777 * Valuenames can have embedded '\'s so be careful.
3778 * only support one level of keys. See the
3779 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3783 str = strchr_m( string, '\\');
3785 /* Put in "PrinterDriverData" is no key specified */
3788 keyname = SPOOL_PRINTERDATA_KEY;
3797 /* see if we need a new key */
3799 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3800 key_index = add_new_printer_key( printer_data, keyname );
3802 if ( key_index == -1 ) {
3803 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3808 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3810 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3811 Thanks to Martin Zielinski for the hint. */
3813 if ( type == REG_BINARY &&
3814 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3815 strequal( valuename, "objectGUID" ) )
3819 /* convert the GUID to a UNICODE string */
3821 memcpy( &guid, data_p, sizeof(struct GUID) );
3823 regval_ctr_addvalue_sz(printer_data->keys[key_index].values,
3825 GUID_string(talloc_tos(), &guid));
3830 regval_ctr_addvalue( printer_data->keys[key_index].values,
3831 valuename, type, (const char *)data_p,
3835 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3842 /****************************************************************************
3843 ***************************************************************************/
3845 static char *win_driver;
3846 static char *os2_driver;
3848 static const char *get_win_driver(void)
3850 if (win_driver == NULL) {
3856 static const char *get_os2_driver(void)
3858 if (os2_driver == NULL) {
3864 static bool set_driver_mapping(const char *from, const char *to)
3866 SAFE_FREE(win_driver);
3867 SAFE_FREE(os2_driver);
3869 win_driver = SMB_STRDUP(from);
3870 os2_driver = SMB_STRDUP(to);
3872 if (win_driver == NULL || os2_driver == NULL) {
3873 SAFE_FREE(win_driver);
3874 SAFE_FREE(os2_driver);
3880 static void map_to_os2_driver(fstring drivername)
3882 char *mapfile = lp_os2_driver_map();
3883 char **lines = NULL;
3887 if (!strlen(drivername))
3893 if (strequal(drivername, get_win_driver())) {
3894 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3895 drivername, get_os2_driver()));
3896 fstrcpy(drivername, get_os2_driver());
3900 lines = file_lines_load(mapfile, &numlines,0,NULL);
3901 if (numlines == 0 || lines == NULL) {
3902 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3907 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3909 for( i = 0; i < numlines; i++) {
3910 char *nt_name = lines[i];
3911 char *os2_name = strchr(nt_name,'=');
3918 while (isspace(*nt_name))
3921 if (!*nt_name || strchr("#;",*nt_name))
3925 int l = strlen(nt_name);
3926 while (l && isspace(nt_name[l-1])) {
3932 while (isspace(*os2_name))
3936 int l = strlen(os2_name);
3937 while (l && isspace(os2_name[l-1])) {
3943 if (strequal(nt_name,drivername)) {
3944 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3945 set_driver_mapping(drivername,os2_name);
3946 fstrcpy(drivername,os2_name);
3958 * @brief Map a Windows driver to a OS/2 driver.
3960 * @param[in] mem_ctx The memory context to use.
3962 * @param[in,out] pdrivername The drivername of Windows to remap.
3964 * @return WERR_OK on success, a corresponding WERROR on failure.
3966 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
3968 const char *mapfile = lp_os2_driver_map();
3969 char **lines = NULL;
3970 const char *drivername;
3974 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
3975 return WERR_INVALID_PARAMETER;
3978 drivername = *pdrivername;
3980 if (mapfile[0] == '\0') {
3981 return WERR_BADFILE;
3984 if (strequal(drivername, get_win_driver())) {
3985 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3986 drivername, get_os2_driver()));
3987 drivername = talloc_strdup(mem_ctx, get_os2_driver());
3988 if (drivername == NULL) {
3991 *pdrivername = drivername;
3995 lines = file_lines_load(mapfile, &numlines, 0, NULL);
3996 if (numlines == 0 || lines == NULL) {
3997 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
4002 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
4004 for( i = 0; i < numlines; i++) {
4005 char *nt_name = lines[i];
4006 char *os2_name = strchr(nt_name, '=');
4008 if (os2_name == NULL) {
4014 while (isspace(*nt_name)) {
4018 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
4023 int l = strlen(nt_name);
4024 while (l && isspace(nt_name[l - 1])) {
4030 while (isspace(*os2_name)) {
4035 int l = strlen(os2_name);
4036 while (l && isspace(os2_name[l-1])) {
4042 if (strequal(nt_name, drivername)) {
4043 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
4044 set_driver_mapping(drivername, os2_name);
4045 drivername = talloc_strdup(mem_ctx, os2_name);
4047 if (drivername == NULL) {
4050 *pdrivername = drivername;
4059 /****************************************************************************
4060 Get a default printer info 2 struct.
4061 ****************************************************************************/
4063 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
4064 const char *servername,
4065 const char* sharename,
4068 int snum = lp_servicenumber(sharename);
4070 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4071 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4072 servername, sharename);
4073 fstrcpy(info->sharename, sharename);
4074 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
4076 /* by setting the driver name to an empty string, a local NT admin
4077 can now run the **local** APW to install a local printer driver
4078 for a Samba shared printer in 2.2. Without this, drivers **must** be
4079 installed on the Samba server for NT clients --jerry */
4080 #if 0 /* JERRY --do not uncomment-- */
4081 if (!*info->drivername)
4082 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
4086 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
4088 strlcpy(info->comment, "", sizeof(info->comment));
4089 fstrcpy(info->printprocessor, "winprint");
4090 fstrcpy(info->datatype, "RAW");
4093 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4094 /* Pull the location and comment strings from cups if we don't
4096 if ( !strlen(info->location) || !strlen(info->comment) ) {
4097 char *comment = NULL;
4098 char *location = NULL;
4099 if (cups_pull_comment_location(info, info->sharename,
4100 &comment, &location)) {
4101 strlcpy(info->comment, comment, sizeof(info->comment));
4102 fstrcpy(info->location, location);
4103 TALLOC_FREE(comment);
4104 TALLOC_FREE(location);
4110 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
4112 info->starttime = 0; /* Minutes since 12:00am GMT */
4113 info->untiltime = 0; /* Minutes since 12:00am GMT */
4115 info->default_priority = 1;
4116 info->setuptime = (uint32)time(NULL);
4119 * I changed this as I think it is better to have a generic
4120 * DEVMODE than to crash Win2k explorer.exe --jerry
4121 * See the HP Deskjet 990c Win2k drivers for an example.
4123 * However the default devmode appears to cause problems
4124 * with the HP CLJ 8500 PCL driver. Hence the addition of
4125 * the "default devmode" parameter --jerry 22/01/2002
4128 if (lp_default_devmode(snum)) {
4129 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
4133 info->devmode = NULL;
4136 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4140 info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
4145 add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
4151 free_nt_devicemode(&info->devmode);
4153 return WERR_ACCESS_DENIED;
4156 /****************************************************************************
4157 ****************************************************************************/
4159 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
4160 const char *servername,
4161 const char *sharename,
4165 int snum = lp_servicenumber(sharename);
4166 TDB_DATA kbuf, dbuf;
4167 fstring printername;
4168 char adevice[MAXDEVICENAME];
4169 char *comment = NULL;
4171 kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4173 dbuf = tdb_fetch(tdb_printers, kbuf);
4175 return get_a_printer_2_default(info, servername,
4176 sharename, get_loc_com);
4179 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4182 &info->default_priority,
4189 &info->c_setprinter,
4199 info->printprocessor,
4204 strlcpy(info->comment, comment, sizeof(info->comment));
4208 /* Samba has to have shared raw drivers. */
4209 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4210 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4212 /* Restore the stripped strings. */
4213 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4215 if ( lp_force_printername(snum) ) {
4216 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4218 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4221 fstrcpy(info->printername, printername);
4224 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4225 /* Pull the location and comment strings from cups if we don't
4227 if ( !strlen(info->location) || !strlen(info->comment) ) {
4228 char *location = NULL;
4230 if (cups_pull_comment_location(info, info->sharename,
4231 &comment, &location)) {
4232 strlcpy(info->comment, comment, sizeof(info->comment));
4233 fstrcpy(info->location, location);
4234 TALLOC_FREE(comment);
4235 TALLOC_FREE(location);
4241 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4244 * Some client drivers freak out if there is a NULL devmode
4245 * (probably the driver is not checking before accessing
4246 * the devmode pointer) --jerry
4248 * See comments in get_a_printer_2_default()
4251 if (lp_default_devmode(snum) && !info->devmode) {
4252 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4254 info->devmode = construct_nt_devicemode(printername);
4257 slprintf( adevice, sizeof(adevice), "%s", info->printername );
4258 if (info->devmode) {
4259 fstrcpy(info->devmode->devicename, adevice);
4262 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4263 DEBUG(0,("unpack_values: talloc() failed!\n"));
4264 SAFE_FREE(dbuf.dptr);
4267 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4269 /* This will get the current RPC talloc context, but we should be
4270 passing this as a parameter... fixme... JRA ! */
4272 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4273 SAFE_FREE(dbuf.dptr);
4277 /* Fix for OS/2 drivers. */
4279 if (get_remote_arch() == RA_OS2) {
4280 map_to_os2_driver(info->drivername);
4283 SAFE_FREE(dbuf.dptr);
4285 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4286 sharename, info->printername, info->drivername));
4291 /****************************************************************************
4292 Debugging function, dump at level 6 the struct in the logs.
4293 ****************************************************************************/
4294 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4297 NT_PRINTER_INFO_LEVEL_2 *info2;
4299 DEBUG(106,("Dumping printer at level [%d]\n", level));
4304 if (printer->info_2 == NULL)
4308 info2=printer->info_2;
4310 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4311 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4312 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4313 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4314 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4315 DEBUGADD(106,("status:[%d]\n", info2->status));
4316 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4317 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4318 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4319 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4320 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4322 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4323 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4324 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4325 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4326 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4327 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4328 DEBUGADD(106,("location:[%s]\n", info2->location));
4329 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4330 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4331 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4332 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4338 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4346 /****************************************************************************
4347 Update the changeid time.
4348 This is SO NASTY as some drivers need this to change, others need it
4349 static. This value will change every second, and I must hope that this
4350 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4352 ****************************************************************************/
4354 static uint32 rev_changeid(void)
4358 get_process_uptime(&tv);
4361 /* Return changeid as msec since spooler restart */
4362 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4365 * This setting seems to work well but is too untested
4366 * to replace the above calculation. Left in for experiementation
4367 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4369 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4375 * The function below are the high level ones.
4376 * only those ones must be called from the spoolss code.
4380 /****************************************************************************
4381 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4382 ****************************************************************************/
4384 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4388 dump_a_printer(printer, level);
4394 * Update the changestamp. Emperical tests show that the
4395 * ChangeID is always updated,but c_setprinter is
4396 * global spooler variable (not per printer).
4399 /* ChangeID **must** be increasing over the lifetime
4400 of client's spoolss service in order for the
4401 client's cache to show updates */
4403 printer->info_2->changeid = rev_changeid();
4406 * Because one day someone will ask:
4407 * NT->NT An admin connection to a remote
4408 * printer show changes imeediately in
4409 * the properities dialog
4411 * A non-admin connection will only show the
4412 * changes after viewing the properites page
4413 * 2 times. Seems to be related to a
4414 * race condition in the client between the spooler
4415 * updating the local cache and the Explorer.exe GUI
4416 * actually displaying the properties.
4418 * This is fixed in Win2k. admin/non-admin
4419 * connections both display changes immediately.
4424 result=update_a_printer_2(printer->info_2);
4428 result=WERR_UNKNOWN_LEVEL;
4435 /****************************************************************************
4436 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4438 Previously the code had a memory allocation problem because it always
4439 used the TALLOC_CTX from the Printer_entry*. This context lasts
4440 as a long as the original handle is open. So if the client made a lot
4441 of getprinter[data]() calls, the memory usage would climb. Now we use
4442 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4443 still use the Printer_entry->ctx for maintaining the cache copy though
4444 since that object must live as long as the handle by definition.
4447 ****************************************************************************/
4449 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4450 const char *sharename, bool get_loc_com)
4455 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4457 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4458 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4464 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4465 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4466 TALLOC_FREE( *pp_printer );
4471 fstrcpy( servername, print_hnd->servername );
4473 fstrcpy( servername, "%L" );
4474 standard_sub_basic( "", "", servername,
4475 sizeof(servername)-1 );
4478 result = get_a_printer_2( (*pp_printer)->info_2,
4479 servername, sharename, get_loc_com);
4481 /* we have a new printer now. Save it with this handle */
4483 if ( !W_ERROR_IS_OK(result) ) {
4484 TALLOC_FREE( *pp_printer );
4485 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4486 sharename, (unsigned int)level, win_errstr(result)));
4490 dump_a_printer( *pp_printer, level);
4495 TALLOC_FREE( *pp_printer );
4496 return WERR_UNKNOWN_LEVEL;
4502 WERROR get_a_printer( Printer_entry *print_hnd,
4503 NT_PRINTER_INFO_LEVEL **pp_printer,
4505 const char *sharename)
4507 return get_a_printer_internal(print_hnd, pp_printer, level,
4511 WERROR get_a_printer_search( Printer_entry *print_hnd,
4512 NT_PRINTER_INFO_LEVEL **pp_printer,
4514 const char *sharename)
4516 return get_a_printer_internal(print_hnd, pp_printer, level,
4520 /****************************************************************************
4521 Deletes a NT_PRINTER_INFO_LEVEL struct.
4522 ****************************************************************************/
4524 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4526 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4533 if ( printer->info_2 )
4534 free_nt_printer_info_level_2(&printer->info_2);
4538 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4542 TALLOC_FREE(*pp_printer);
4547 /****************************************************************************
4548 ****************************************************************************/
4550 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
4551 struct spoolss_DriverInfo8 *_info8)
4553 struct spoolss_DriverInfo8 info8;
4559 info8.version = r->info.info3->version;
4560 info8.driver_name = r->info.info3->driver_name;
4561 info8.architecture = r->info.info3->architecture;
4562 info8.driver_path = r->info.info3->driver_path;
4563 info8.data_file = r->info.info3->data_file;
4564 info8.config_file = r->info.info3->config_file;
4565 info8.help_file = r->info.info3->help_file;
4566 info8.monitor_name = r->info.info3->monitor_name;
4567 info8.default_datatype = r->info.info3->default_datatype;
4568 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
4569 info8.dependent_files = r->info.info3->dependent_files->string;
4573 info8.version = r->info.info6->version;
4574 info8.driver_name = r->info.info6->driver_name;
4575 info8.architecture = r->info.info6->architecture;
4576 info8.driver_path = r->info.info6->driver_path;
4577 info8.data_file = r->info.info6->data_file;
4578 info8.config_file = r->info.info6->config_file;
4579 info8.help_file = r->info.info6->help_file;
4580 info8.monitor_name = r->info.info6->monitor_name;
4581 info8.default_datatype = r->info.info6->default_datatype;
4582 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
4583 info8.dependent_files = r->info.info6->dependent_files->string;
4585 info8.driver_date = r->info.info6->driver_date;
4586 info8.driver_version = r->info.info6->driver_version;
4587 info8.manufacturer_name = r->info.info6->manufacturer_name;
4588 info8.manufacturer_url = r->info.info6->manufacturer_url;
4589 info8.hardware_id = r->info.info6->hardware_id;
4590 info8.provider = r->info.info6->provider;
4593 info8.version = r->info.info8->version;
4594 info8.driver_name = r->info.info8->driver_name;
4595 info8.architecture = r->info.info8->architecture;
4596 info8.driver_path = r->info.info8->driver_path;
4597 info8.data_file = r->info.info8->data_file;
4598 info8.config_file = r->info.info8->config_file;
4599 info8.help_file = r->info.info8->help_file;
4600 info8.monitor_name = r->info.info8->monitor_name;
4601 info8.default_datatype = r->info.info8->default_datatype;
4602 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
4603 info8.dependent_files = r->info.info8->dependent_files->string;
4605 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
4606 info8.previous_names = r->info.info8->previous_names->string;
4608 info8.driver_date = r->info.info8->driver_date;
4609 info8.driver_version = r->info.info8->driver_version;
4610 info8.manufacturer_name = r->info.info8->manufacturer_name;
4611 info8.manufacturer_url = r->info.info8->manufacturer_url;
4612 info8.hardware_id = r->info.info8->hardware_id;
4613 info8.provider = r->info.info8->provider;
4614 info8.print_processor = r->info.info8->print_processor;
4615 info8.vendor_setup = r->info.info8->vendor_setup;
4616 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
4617 info8.color_profiles = r->info.info8->color_profiles->string;
4619 info8.inf_path = r->info.info8->inf_path;
4620 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
4621 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
4622 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
4624 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
4625 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
4637 uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx,
4638 struct spoolss_AddDriverInfoCtr *r,
4642 struct spoolss_DriverInfo8 info8;
4646 DEBUG(10,("adding a printer at level [%d]\n", r->level));
4648 if (!driver_info_ctr_to_info8(r, &info8)) {
4652 *driver_name = talloc_strdup(mem_ctx, info8.driver_name);
4653 if (!*driver_name) {
4656 *version = info8.version;
4658 return add_a_printer_driver_8(&info8);
4661 /****************************************************************************
4662 ****************************************************************************/
4664 WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx,
4665 struct spoolss_DriverInfo8 **driver,
4666 const char *drivername, const char *architecture,
4670 struct spoolss_DriverInfo3 info3;
4671 struct spoolss_DriverInfo8 *info8;
4675 /* Sometime we just want any version of the driver */
4677 if (version == DRIVER_ANY_VERSION) {
4678 /* look for Win2k first and then for NT4 */
4679 result = get_a_printer_driver_3(mem_ctx,
4683 if (!W_ERROR_IS_OK(result)) {
4684 result = get_a_printer_driver_3(mem_ctx,
4690 result = get_a_printer_driver_3(mem_ctx,
4697 if (!W_ERROR_IS_OK(result)) {
4701 info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8);
4706 info8->version = info3.version;
4707 info8->driver_name = info3.driver_name;
4708 info8->architecture = info3.architecture;
4709 info8->driver_path = info3.driver_path;
4710 info8->data_file = info3.data_file;
4711 info8->config_file = info3.config_file;
4712 info8->help_file = info3.help_file;
4713 info8->dependent_files = info3.dependent_files;
4714 info8->monitor_name = info3.monitor_name;
4715 info8->default_datatype = info3.default_datatype;
4722 /****************************************************************************
4723 ****************************************************************************/
4725 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver)
4727 talloc_free(driver);
4732 /****************************************************************************
4733 Determine whether or not a particular driver is currently assigned
4735 ****************************************************************************/
4737 bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r)
4740 int n_services = lp_numservices();
4741 NT_PRINTER_INFO_LEVEL *printer = NULL;
4742 bool in_use = False;
4748 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4750 /* loop through the printers.tdb and check for the drivername */
4752 for (snum=0; snum<n_services && !in_use; snum++) {
4753 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4756 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4759 if (strequal(r->driver_name, printer->info_2->drivername))
4762 free_a_printer( &printer, 2 );
4765 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4768 struct spoolss_DriverInfo8 *d;
4771 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
4773 /* we can still remove the driver if there is one of
4774 "Windows NT x86" version 2 or 3 left */
4776 if (!strequal("Windows NT x86", r->architecture)) {
4777 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION);
4780 switch (r->version) {
4782 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3);
4785 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2);
4788 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4790 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4795 /* now check the error code */
4797 if ( W_ERROR_IS_OK(werr) ) {
4798 /* it's ok to remove the driver, we have other architctures left */
4800 free_a_printer_driver(d);
4804 /* report that the driver is not in use by default */
4810 /**********************************************************************
4811 Check to see if a ogiven file is in use by *info
4812 *********************************************************************/
4814 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
4821 /* mz: skip files that are in the list but already deleted */
4822 if (!file || !file[0]) {
4826 if (strequal(file, info->driver_path))
4829 if (strequal(file, info->data_file))
4832 if (strequal(file, info->config_file))
4835 if (strequal(file, info->help_file))
4838 /* see of there are any dependent files to examine */
4840 if (!info->dependent_files)
4843 while (info->dependent_files[i] && *info->dependent_files[i]) {
4844 if (strequal(file, info->dependent_files[i]))
4853 /**********************************************************************
4854 Utility function to remove the dependent file pointed to by the
4855 input parameter from the list
4856 *********************************************************************/
4858 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
4861 /* bump everything down a slot */
4863 while (files && files[idx+1]) {
4864 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
4873 /**********************************************************************
4874 Check if any of the files used by src are also used by drv
4875 *********************************************************************/
4877 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
4878 struct spoolss_DriverInfo8 *src,
4879 const struct spoolss_DriverInfo8 *drv)
4881 bool in_use = False;
4887 /* check each file. Remove it from the src structure if it overlaps */
4889 if (drv_file_in_use(src->driver_path, drv)) {
4891 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
4892 src->driver_path = talloc_strdup(mem_ctx, "");
4893 if (!src->driver_path) { return false; }
4896 if (drv_file_in_use(src->data_file, drv)) {
4898 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
4899 src->data_file = talloc_strdup(mem_ctx, "");
4900 if (!src->data_file) { return false; }
4903 if (drv_file_in_use(src->config_file, drv)) {
4905 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
4906 src->config_file = talloc_strdup(mem_ctx, "");
4907 if (!src->config_file) { return false; }
4910 if (drv_file_in_use(src->help_file, drv)) {
4912 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
4913 src->help_file = talloc_strdup(mem_ctx, "");
4914 if (!src->help_file) { return false; }
4917 /* are there any dependentfiles to examine? */
4919 if (!src->dependent_files)
4922 while (src->dependent_files[i] && *src->dependent_files[i]) {
4923 if (drv_file_in_use(src->dependent_files[i], drv)) {
4925 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
4926 trim_dependent_file(mem_ctx, src->dependent_files, i);
4934 /****************************************************************************
4935 Determine whether or not a particular driver files are currently being
4936 used by any other driver.
4938 Return value is True if any files were in use by other drivers
4939 and False otherwise.
4941 Upon return, *info has been modified to only contain the driver files
4942 which are not in use
4946 This needs to check all drivers to ensure that all files in use
4947 have been removed from *info, not just the ones in the first
4949 ****************************************************************************/
4951 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
4952 struct spoolss_DriverInfo8 *info)
4957 fstring *list = NULL;
4958 struct spoolss_DriverInfo8 *driver;
4959 bool in_use = false;
4964 version = info->version;
4966 /* loop over all driver versions */
4968 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4970 /* get the list of drivers */
4973 ndrivers = get_ntdrivers(&list, info->architecture, version);
4975 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4976 ndrivers, info->architecture, version));
4978 /* check each driver for overlap in files */
4980 for (i=0; i<ndrivers; i++) {
4981 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4985 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, list[i], info->architecture, version))) {
4990 /* check if d2 uses any files from d1 */
4991 /* only if this is a different driver than the one being deleted */
4993 if (!strequal(info->driver_name, driver->driver_name)) {
4994 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
4995 /* mz: Do not instantly return -
4996 * we need to ensure this file isn't
4997 * also in use by other drivers. */
5002 free_a_printer_driver(driver);
5007 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5012 static NTSTATUS driver_unlink_internals(connection_struct *conn,
5015 struct smb_filename *smb_fname = NULL;
5018 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
5020 if (!NT_STATUS_IS_OK(status)) {
5024 status = unlink_internals(conn, NULL, 0, smb_fname, false);
5026 TALLOC_FREE(smb_fname);
5030 /****************************************************************************
5031 Actually delete the driver files. Make sure that
5032 printer_driver_files_in_use() return False before calling
5034 ****************************************************************************/
5036 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
5037 const struct spoolss_DriverInfo8 *r)
5042 connection_struct *conn;
5045 fstring printdollar;
5046 int printdollar_snum;
5053 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
5054 r->driver_name, r->version));
5056 fstrcpy(printdollar, "print$");
5058 printdollar_snum = find_service(printdollar);
5059 if (printdollar_snum == -1) {
5063 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5064 lp_pathname(printdollar_snum),
5065 rpc_pipe->server_info, &oldcwd);
5066 if (!NT_STATUS_IS_OK(nt_status)) {
5067 DEBUG(0,("delete_driver_files: create_conn_struct "
5068 "returned %s\n", nt_errstr(nt_status)));
5072 if ( !CAN_WRITE(conn) ) {
5073 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5077 /* now delete the files; must strip the '\print$' string from
5080 if (r->driver_path && r->driver_path[0]) {
5081 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
5083 DEBUG(10,("deleting driverfile [%s]\n", s));
5084 driver_unlink_internals(conn, file);
5088 if (r->config_file && r->config_file[0]) {
5089 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
5091 DEBUG(10,("deleting configfile [%s]\n", s));
5092 driver_unlink_internals(conn, file);
5096 if (r->data_file && r->data_file[0]) {
5097 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
5099 DEBUG(10,("deleting datafile [%s]\n", s));
5100 driver_unlink_internals(conn, file);
5104 if (r->help_file && r->help_file[0]) {
5105 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
5107 DEBUG(10,("deleting helpfile [%s]\n", s));
5108 driver_unlink_internals(conn, file);
5112 /* check if we are done removing files */
5114 if (r->dependent_files) {
5115 while (r->dependent_files[i] && r->dependent_files[i][0]) {
5118 /* bypass the "\print$" portion of the path */
5120 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
5122 DEBUG(10,("deleting dependent file [%s]\n", file));
5123 driver_unlink_internals(conn, file);
5135 vfs_ChDir(conn, oldcwd);
5141 /****************************************************************************
5142 Remove a printer driver from the TDB. This assumes that the the driver was
5143 previously looked up.
5144 ***************************************************************************/
5146 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5147 const struct spoolss_DriverInfo8 *r,
5148 uint32 version, bool delete_files )
5154 /* delete the tdb data first */
5156 arch = get_short_archi(r->architecture);
5158 return WERR_UNKNOWN_PRINTER_DRIVER;
5160 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5161 arch, version, r->driver_name) < 0) {
5165 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5166 key, delete_files ? "TRUE" : "FALSE" ));
5168 /* check if the driver actually exists for this environment */
5170 dbuf = tdb_fetch_bystring( tdb_drivers, key );
5172 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5174 return WERR_UNKNOWN_PRINTER_DRIVER;
5177 SAFE_FREE( dbuf.dptr );
5179 /* ok... the driver exists so the delete should return success */
5181 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5182 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5184 return WERR_ACCESS_DENIED;
5188 * now delete any associated files if delete_files == True
5189 * even if this part failes, we return succes because the
5190 * driver doesn not exist any more
5194 delete_driver_files(rpc_pipe, r);
5196 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5202 /****************************************************************************
5203 Store a security desc for a printer.
5204 ****************************************************************************/
5206 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
5208 struct sec_desc_buf *new_secdesc_ctr = NULL;
5209 struct sec_desc_buf *old_secdesc_ctr = NULL;
5210 TALLOC_CTX *mem_ctx = NULL;
5217 mem_ctx = talloc_init("nt_printing_setsec");
5218 if (mem_ctx == NULL)
5221 /* The old owner and group sids of the security descriptor are not
5222 present when new ACEs are added or removed by changing printer
5223 permissions through NT. If they are NULL in the new security
5224 descriptor then copy them over from the old one. */
5226 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5227 DOM_SID *owner_sid, *group_sid;
5228 struct security_acl *dacl, *sacl;
5229 struct security_descriptor *psd = NULL;
5232 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5233 status = WERR_NOMEM;
5237 /* Pick out correct owner and group sids */
5239 owner_sid = secdesc_ctr->sd->owner_sid ?
5240 secdesc_ctr->sd->owner_sid :
5241 old_secdesc_ctr->sd->owner_sid;
5243 group_sid = secdesc_ctr->sd->group_sid ?
5244 secdesc_ctr->sd->group_sid :
5245 old_secdesc_ctr->sd->group_sid;
5247 dacl = secdesc_ctr->sd->dacl ?
5248 secdesc_ctr->sd->dacl :
5249 old_secdesc_ctr->sd->dacl;
5251 sacl = secdesc_ctr->sd->sacl ?
5252 secdesc_ctr->sd->sacl :
5253 old_secdesc_ctr->sd->sacl;
5255 /* Make a deep copy of the security descriptor */
5257 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5258 owner_sid, group_sid,
5264 status = WERR_NOMEM;
5268 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5271 if (!new_secdesc_ctr) {
5272 new_secdesc_ctr = secdesc_ctr;
5275 /* Store the security descriptor in a tdb */
5277 nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5278 &blob.data, &blob.length);
5279 if (!NT_STATUS_IS_OK(nt_status)) {
5280 status = ntstatus_to_werror(nt_status);
5284 kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5286 dbuf.dptr = (unsigned char *)blob.data;
5287 dbuf.dsize = blob.length;
5289 if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5292 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5293 status = WERR_BADFUNC;
5296 /* Free malloc'ed memory */
5297 talloc_free(blob.data);
5302 talloc_destroy(mem_ctx);
5306 /****************************************************************************
5307 Construct a default security descriptor buffer for a printer.
5308 ****************************************************************************/
5310 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
5312 struct security_ace ace[5]; /* max number of ace entries */
5315 struct security_acl *psa = NULL;
5316 struct sec_desc_buf *sdb = NULL;
5317 struct security_descriptor *psd = NULL;
5321 /* Create an ACE where Everyone is allowed to print */
5323 sa = PRINTER_ACE_PRINT;
5324 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5325 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5327 /* Add the domain admins group if we are a DC */
5330 DOM_SID domadmins_sid;
5332 sid_compose(&domadmins_sid, get_global_sam_sid(),
5335 sa = PRINTER_ACE_FULL_CONTROL;
5336 init_sec_ace(&ace[i++], &domadmins_sid,
5337 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5338 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5339 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5340 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5342 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5343 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
5345 sa = PRINTER_ACE_FULL_CONTROL;
5346 init_sec_ace(&ace[i++], &adm_sid,
5347 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5348 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5349 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5350 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5353 /* add BUILTIN\Administrators as FULL CONTROL */
5355 sa = PRINTER_ACE_FULL_CONTROL;
5356 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5357 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5358 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5359 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5360 SEC_ACE_TYPE_ACCESS_ALLOWED,
5361 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5363 /* Make the security descriptor owned by the BUILTIN\Administrators */
5365 /* The ACL revision number in rpc_secdesc.h differs from the one
5366 created by NT when setting ACE entries in printer
5367 descriptors. NT4 complains about the property being edited by a
5370 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5371 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
5372 &global_sid_Builtin_Administrators,
5373 &global_sid_Builtin_Administrators,
5374 NULL, psa, &sd_size);
5378 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5382 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5384 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5385 (unsigned int)sd_size));
5390 /****************************************************************************
5391 Get a security desc for a printer.
5392 ****************************************************************************/
5394 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
5402 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5403 sharename = temp + 1;
5406 /* Fetch security descriptor from tdb */
5408 kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5410 dbuf = tdb_fetch(tdb_printers, kbuf);
5413 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5415 SAFE_FREE(dbuf.dptr);
5417 if (NT_STATUS_IS_OK(status)) {
5422 *secdesc_ctr = construct_default_printer_sdb(ctx);
5423 if (!*secdesc_ctr) {
5427 status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5428 &blob.data, &blob.length);
5429 if (NT_STATUS_IS_OK(status)) {
5430 dbuf.dptr = (unsigned char *)blob.data;
5431 dbuf.dsize = blob.length;
5432 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5433 talloc_free(blob.data);
5436 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5437 this security descriptor has been created when winbindd was
5438 down. Take ownership of security descriptor. */
5440 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5443 /* Change sd owner to workgroup administrator */
5445 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5446 struct sec_desc_buf *new_secdesc_ctr = NULL;
5447 struct security_descriptor *psd = NULL;
5452 sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
5454 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5456 (*secdesc_ctr)->sd->group_sid,
5457 (*secdesc_ctr)->sd->sacl,
5458 (*secdesc_ctr)->sd->dacl,
5465 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5466 if (!new_secdesc_ctr) {
5470 /* Swap with other one */
5472 *secdesc_ctr = new_secdesc_ctr;
5476 nt_printing_setsec(sharename, *secdesc_ctr);
5480 if (DEBUGLEVEL >= 10) {
5481 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
5484 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5485 sharename, the_acl->num_aces));
5487 for (i = 0; i < the_acl->num_aces; i++) {
5488 DEBUG(10, ("%s %d %d 0x%08x\n",
5489 sid_string_dbg(&the_acl->aces[i].trustee),
5490 the_acl->aces[i].type, the_acl->aces[i].flags,
5491 the_acl->aces[i].access_mask));
5500 1: level not implemented
5501 2: file doesn't exist
5502 3: can't allocate memory
5503 4: can't free memory
5504 5: non existant struct
5508 A printer and a printer driver are 2 different things.
5509 NT manages them separatelly, Samba does the same.
5510 Why ? Simply because it's easier and it makes sense !
5512 Now explanation: You have 3 printers behind your samba server,
5513 2 of them are the same make and model (laser A and B). But laser B
5514 has an 3000 sheet feeder and laser A doesn't such an option.
5515 Your third printer is an old dot-matrix model for the accounting :-).
5517 If the /usr/local/samba/lib directory (default dir), you will have
5518 5 files to describe all of this.
5520 3 files for the printers (1 by printer):
5523 NTprinter_accounting
5524 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5525 NTdriver_printer model X
5526 NTdriver_printer model Y
5528 jfm: I should use this comment for the text file to explain
5529 same thing for the forms BTW.
5530 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5534 /* Convert generic access rights to printer object specific access rights.
5535 It turns out that NT4 security descriptors use generic access rights and
5536 NT5 the object specific ones. */
5538 void map_printer_permissions(struct security_descriptor *sd)
5542 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5543 se_map_generic(&sd->dacl->aces[i].access_mask,
5544 &printer_generic_mapping);
5548 void map_job_permissions(struct security_descriptor *sd)
5552 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5553 se_map_generic(&sd->dacl->aces[i].access_mask,
5554 &job_generic_mapping);
5559 /****************************************************************************
5560 Check a user has permissions to perform the given operation. We use the
5561 permission constants defined in include/rpc_spoolss.h to check the various
5562 actions we perform when checking printer access.
5564 PRINTER_ACCESS_ADMINISTER:
5565 print_queue_pause, print_queue_resume, update_printer_sec,
5566 update_printer, spoolss_addprinterex_level_2,
5567 _spoolss_setprinterdata
5572 JOB_ACCESS_ADMINISTER:
5573 print_job_delete, print_job_pause, print_job_resume,
5576 Try access control in the following order (for performance reasons):
5577 1) root and SE_PRINT_OPERATOR can do anything (easy check)
5578 2) check security descriptor (bit comparisons in memory)
5579 3) "printer admins" (may result in numerous calls to winbind)
5581 ****************************************************************************/
5582 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5585 struct sec_desc_buf *secdesc = NULL;
5586 uint32 access_granted;
5589 TALLOC_CTX *mem_ctx = NULL;
5590 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5592 /* If user is NULL then use the current_user structure */
5594 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5596 if (server_info->utok.uid == sec_initial_uid()
5597 || user_has_privileges(server_info->ptok, &se_printop ) ) {
5601 /* Get printer name */
5603 pname = PRINTERNAME(snum);
5605 if (!pname || !*pname) {
5610 /* Get printer security descriptor */
5612 if(!(mem_ctx = talloc_init("print_access_check"))) {
5617 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5618 talloc_destroy(mem_ctx);
5623 if (access_type == JOB_ACCESS_ADMINISTER) {
5624 struct sec_desc_buf *parent_secdesc = secdesc;
5626 /* Create a child security descriptor to check permissions
5627 against. This is because print jobs are child objects
5628 objects of a printer. */
5630 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5632 if (!NT_STATUS_IS_OK(status)) {
5633 talloc_destroy(mem_ctx);
5634 errno = map_errno_from_nt_status(status);
5638 map_job_permissions(secdesc->sd);
5640 map_printer_permissions(secdesc->sd);
5644 status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5647 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5649 /* see if we need to try the printer admin list */
5651 if (!NT_STATUS_IS_OK(status) &&
5652 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5653 NULL, NULL, server_info->ptok,
5654 lp_printer_admin(snum)))) {
5655 talloc_destroy(mem_ctx);
5659 talloc_destroy(mem_ctx);
5661 if (!NT_STATUS_IS_OK(status)) {
5665 return NT_STATUS_IS_OK(status);
5668 /****************************************************************************
5669 Check the time parameters allow a print operation.
5670 *****************************************************************************/
5672 bool print_time_access_check(const char *servicename)
5674 NT_PRINTER_INFO_LEVEL *printer = NULL;
5676 time_t now = time(NULL);
5680 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5683 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5687 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5689 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5692 free_a_printer(&printer, 2);
5700 /****************************************************************************
5701 Fill in the servername sent in the _spoolss_open_printer_ex() call
5702 ****************************************************************************/
5704 char* get_server_name( Printer_entry *printer )
5706 return printer->servername;