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 {"A0",0x1,0xcd528,0x122488,0x0,0x0,0xcd528,0x122488},
97 {"A1",0x1,0x91050,0xcd528,0x0,0x0,0x91050,0xcd528},
98 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
99 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
100 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
101 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
102 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
103 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
104 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
105 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
106 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
107 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
108 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
109 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
110 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
111 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
112 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
113 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
114 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
115 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
116 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
117 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
118 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
119 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
120 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
121 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
122 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
123 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
124 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
125 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
126 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
127 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
128 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
129 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
130 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
131 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
132 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
133 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
134 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
135 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
136 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
137 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
138 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
139 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
140 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
141 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
142 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
143 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
144 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
145 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
146 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
147 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
148 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
149 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
150 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
151 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
152 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
153 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
154 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
155 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
156 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
157 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
158 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
159 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
160 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
161 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
162 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
163 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
164 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
165 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
166 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
167 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
168 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
169 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
170 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
171 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
172 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
173 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
174 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
175 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
176 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
177 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
178 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
179 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
180 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
181 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
182 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
183 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
184 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
185 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
186 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
187 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
188 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
189 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
190 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
191 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
192 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
193 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
194 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
195 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
196 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
197 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
198 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
199 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
200 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
201 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
202 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
203 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
204 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
205 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
206 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
207 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
208 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
211 static const struct print_architecture_table_node archi_table[]= {
213 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
214 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
215 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
216 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
217 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
218 {"Windows IA64", SPL_ARCH_IA64, 3 },
219 {"Windows x64", SPL_ARCH_X64, 3 },
224 /****************************************************************************
225 generate a new TDB_DATA key for storing a printer
226 ****************************************************************************/
228 static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
234 fstrcpy(share, sharename);
237 keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
238 key = string_term_tdb_data(keystr ? keystr : "");
243 /****************************************************************************
244 generate a new TDB_DATA key for storing a printer security descriptor
245 ****************************************************************************/
247 static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
248 const char* sharename )
254 fstrcpy(share, sharename );
257 keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
258 key = string_term_tdb_data(keystr ? keystr : "");
263 /****************************************************************************
264 ****************************************************************************/
266 static bool upgrade_to_version_3(void)
268 TDB_DATA kbuf, newkey, dbuf;
270 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
272 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
273 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
275 dbuf = tdb_fetch(tdb_drivers, kbuf);
277 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
278 DEBUG(0,("upgrade_to_version_3:moving form\n"));
279 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
280 SAFE_FREE(dbuf.dptr);
281 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
284 if (tdb_delete(tdb_drivers, kbuf) != 0) {
285 SAFE_FREE(dbuf.dptr);
286 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
291 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
292 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
293 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
294 SAFE_FREE(dbuf.dptr);
295 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
298 if (tdb_delete(tdb_drivers, kbuf) != 0) {
299 SAFE_FREE(dbuf.dptr);
300 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
305 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
306 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
307 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
308 SAFE_FREE(dbuf.dptr);
309 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
312 if (tdb_delete(tdb_drivers, kbuf) != 0) {
313 SAFE_FREE(dbuf.dptr);
314 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
319 SAFE_FREE(dbuf.dptr);
325 /*******************************************************************
326 Fix an issue with security descriptors. Printer sec_desc must
327 use more than the generic bits that were previously used
328 in <= 3.0.14a. They must also have a owner and group SID assigned.
329 Otherwise, any printers than have been migrated to a Windows
330 host using printmig.exe will not be accessible.
331 *******************************************************************/
333 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
334 TDB_DATA data, void *state )
337 struct sec_desc_buf *sd_orig = NULL;
338 struct sec_desc_buf *sd_new, *sd_store;
339 struct security_descriptor *sec, *new_sec;
340 TALLOC_CTX *ctx = state;
345 if (!data.dptr || data.dsize == 0) {
349 if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
353 /* upgrade the security descriptor */
355 status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
356 if (!NT_STATUS_IS_OK(status)) {
357 /* delete bad entries */
358 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
359 (const char *)key.dptr ));
360 tdb_delete( tdb_printers, key );
369 /* is this even valid? */
375 /* update access masks */
377 for ( i=0; i<sec->dacl->num_aces; i++ ) {
378 switch ( sec->dacl->aces[i].access_mask ) {
379 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
380 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
383 case GENERIC_ALL_ACCESS:
384 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
387 case READ_CONTROL_ACCESS:
388 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
390 default: /* no change */
395 /* create a new struct security_descriptor with the appropriate owner and group SIDs */
397 new_sec = make_sec_desc( ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
398 &global_sid_Builtin_Administrators,
399 &global_sid_Builtin_Administrators,
400 NULL, NULL, &size_new_sec );
404 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
409 if ( !(sd_store = sec_desc_merge_buf( ctx, sd_new, sd_orig )) ) {
410 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
416 sd_size = ndr_size_security_descriptor(sd_store->sd, 0)
417 + sizeof(struct sec_desc_buf);
419 status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
420 if (!NT_STATUS_IS_OK(status)) {
421 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
425 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
427 /* 0 to continue and non-zero to stop traversal */
429 return (result == -1);
432 /*******************************************************************
433 *******************************************************************/
435 static bool upgrade_to_version_4(void)
440 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
442 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
445 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
447 talloc_destroy( ctx );
449 return ( result != -1 );
452 /*******************************************************************
453 Fix an issue with security descriptors. Printer sec_desc must
454 use more than the generic bits that were previously used
455 in <= 3.0.14a. They must also have a owner and group SID assigned.
456 Otherwise, any printers than have been migrated to a Windows
457 host using printmig.exe will not be accessible.
458 *******************************************************************/
460 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
461 TDB_DATA data, void *state )
463 TALLOC_CTX *ctx = talloc_tos();
466 if (!data.dptr || data.dsize == 0)
469 /* upgrade printer records and security descriptors */
471 if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
472 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
474 else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
475 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
478 /* ignore this record */
482 /* delete the original record and store under the normalized key */
484 if ( tdb_delete( the_tdb, key ) != 0 ) {
485 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
490 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
491 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
499 /*******************************************************************
500 *******************************************************************/
502 static bool upgrade_to_version_5(void)
507 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
509 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
512 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
514 talloc_destroy( ctx );
516 return ( result != -1 );
519 /****************************************************************************
520 Open the NT printing tdbs. Done once before fork().
521 ****************************************************************************/
523 bool nt_printing_init(struct messaging_context *msg_ctx)
525 const char *vstring = "INFO/version";
529 if ( tdb_drivers && tdb_printers && tdb_forms )
533 tdb_close(tdb_drivers);
534 tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
536 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
537 state_path("ntdrivers.tdb"), strerror(errno) ));
542 tdb_close(tdb_printers);
543 tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
545 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
546 state_path("ntprinters.tdb"), strerror(errno) ));
551 tdb_close(tdb_forms);
552 tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
554 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
555 state_path("ntforms.tdb"), strerror(errno) ));
559 /* handle a Samba upgrade */
561 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
563 DEBUG(10, ("Fresh database\n"));
564 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
565 vers_id = NTDRIVERS_DATABASE_VERSION_5;
568 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
570 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
571 if (!upgrade_to_version_3())
573 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
574 vers_id = NTDRIVERS_DATABASE_VERSION_3;
577 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
578 /* Written on a bigendian machine with old fetch_int code. Save as le. */
579 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
580 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
581 vers_id = NTDRIVERS_DATABASE_VERSION_3;
584 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
585 if ( !upgrade_to_version_4() )
587 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
588 vers_id = NTDRIVERS_DATABASE_VERSION_4;
591 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
592 if ( !upgrade_to_version_5() )
594 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
595 vers_id = NTDRIVERS_DATABASE_VERSION_5;
599 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
600 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
605 update_c_setprinter(True);
608 * register callback to handle updating printers as new
609 * drivers are installed
612 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
613 do_drv_upgrade_printer);
615 /* of course, none of the message callbacks matter if you don't
616 tell messages.c that you interested in receiving PRINT_GENERAL
617 msgs. This is done in serverid_register() */
620 if ( lp_security() == SEC_ADS ) {
621 win_rc = check_published_printers();
622 if (!W_ERROR_IS_OK(win_rc))
623 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
629 /*******************************************************************
630 Function to allow filename parsing "the old way".
631 ********************************************************************/
633 static NTSTATUS driver_unix_convert(connection_struct *conn,
634 const char *old_name,
635 struct smb_filename **smb_fname)
638 TALLOC_CTX *ctx = talloc_tos();
639 char *name = talloc_strdup(ctx, old_name);
642 return NT_STATUS_NO_MEMORY;
645 name = unix_clean_name(ctx, name);
647 return NT_STATUS_NO_MEMORY;
649 trim_string(name,"/","/");
651 status = unix_convert(ctx, conn, name, smb_fname, 0);
652 if (!NT_STATUS_IS_OK(status)) {
653 return NT_STATUS_NO_MEMORY;
659 /*******************************************************************
660 tdb traversal function for counting printers.
661 ********************************************************************/
663 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
664 TDB_DATA data, void *context)
666 int *printer_count = (int*)context;
668 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
670 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
676 /*******************************************************************
677 Update the spooler global c_setprinter. This variable is initialized
678 when the parent smbd starts with the number of existing printers. It
679 is monotonically increased by the current number of printers *after*
680 each add or delete printer RPC. Only Microsoft knows why... JRR020119
681 ********************************************************************/
683 uint32 update_c_setprinter(bool initialize)
686 int32 printer_count = 0;
688 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
690 /* Traverse the tdb, counting the printers */
691 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
693 /* If initializing, set c_setprinter to current printers count
694 * otherwise, bump it by the current printer count
697 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
699 c_setprinter = printer_count;
701 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
702 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
704 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
706 return (uint32)c_setprinter;
709 /*******************************************************************
710 Get the spooler global c_setprinter, accounting for initialization.
711 ********************************************************************/
713 uint32 get_c_setprinter(void)
715 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
717 if (c_setprinter == (int32)-1)
718 c_setprinter = update_c_setprinter(True);
720 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
722 return (uint32)c_setprinter;
725 /****************************************************************************
726 Get builtin form struct list.
727 ****************************************************************************/
729 int get_builtin_ntforms(nt_forms_struct **list)
731 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
735 return ARRAY_SIZE(default_forms);
738 /****************************************************************************
739 get a builtin form struct
740 ****************************************************************************/
742 bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
745 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
746 for (i=0; i<ARRAY_SIZE(default_forms); i++) {
747 if (strequal(form_name,default_forms[i].name)) {
748 DEBUGADD(6,("Found builtin form %s \n", form_name));
749 memcpy(form,&default_forms[i],sizeof(*form));
757 /****************************************************************************
758 get a form struct list.
759 ****************************************************************************/
761 int get_ntforms(nt_forms_struct **list)
763 TDB_DATA kbuf, newkey, dbuf;
764 nt_forms_struct form;
771 for (kbuf = tdb_firstkey(tdb_forms);
773 newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
775 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
778 dbuf = tdb_fetch(tdb_forms, kbuf);
782 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
783 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
784 &i, &form.flag, &form.width, &form.length, &form.left,
785 &form.top, &form.right, &form.bottom);
786 SAFE_FREE(dbuf.dptr);
787 if (ret != dbuf.dsize)
790 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
792 DEBUG(0,("get_ntforms: Realloc fail.\n"));
803 /****************************************************************************
804 write a form struct list
805 ****************************************************************************/
807 int write_ntforms(nt_forms_struct **list, int number)
809 TALLOC_CTX *ctx = talloc_tos();
816 for (i=0;i<number;i++) {
817 /* save index, so list is rebuilt in correct order */
818 len = tdb_pack(NULL, 0, "dddddddd",
819 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
820 (*list)[i].left, (*list)[i].top, (*list)[i].right,
825 buf = TALLOC_ARRAY(ctx, char, len);
829 len = tdb_pack((uint8 *)buf, len, "dddddddd",
830 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
831 (*list)[i].left, (*list)[i].top, (*list)[i].right,
833 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
838 dbuf.dptr = (uint8 *)buf;
839 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
851 /****************************************************************************
852 add a form struct at the end of the list
853 ****************************************************************************/
854 bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count)
860 * NT tries to add forms even when
861 * they are already in the base
862 * only update the values if already present
867 for (n=0; n<*count; n++) {
868 if ( strequal((*list)[n].name, form->form_name) ) {
875 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
876 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
879 fstrcpy((*list)[n].name, form->form_name);
883 (*list)[n].flag = form->flags;
884 (*list)[n].width = form->size.width;
885 (*list)[n].length = form->size.height;
886 (*list)[n].left = form->area.left;
887 (*list)[n].top = form->area.top;
888 (*list)[n].right = form->area.right;
889 (*list)[n].bottom = form->area.bottom;
891 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
892 update ? "updated" : "added", form->form_name));
897 /****************************************************************************
898 Delete a named form struct.
899 ****************************************************************************/
901 bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
908 for (n=0; n<*count; n++) {
909 if (!strncmp((*list)[n].name, del_name, strlen(del_name))) {
910 DEBUG(103, ("delete_a_form, [%s] in list\n", del_name));
916 DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
917 *ret = WERR_INVALID_FORM_NAME;
921 if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
925 if (tdb_delete_bystring(tdb_forms, key) != 0) {
934 /****************************************************************************
935 Update a form struct.
936 ****************************************************************************/
938 void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
942 DEBUG(106, ("[%s]\n", form->form_name));
943 for (n=0; n<count; n++) {
944 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
945 if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name)))
949 if (n==count) return;
951 (*list)[n].flag = form->flags;
952 (*list)[n].width = form->size.width;
953 (*list)[n].length = form->size.height;
954 (*list)[n].left = form->area.left;
955 (*list)[n].top = form->area.top;
956 (*list)[n].right = form->area.right;
957 (*list)[n].bottom = form->area.bottom;
960 /****************************************************************************
961 Get the nt drivers list.
962 Traverse the database and look-up the matching names.
963 ****************************************************************************/
964 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
967 const char *short_archi;
969 TDB_DATA kbuf, newkey;
971 short_archi = get_short_archi(architecture);
976 if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
977 short_archi, version) < 0) {
981 for (kbuf = tdb_firstkey(tdb_drivers);
983 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
985 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
988 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
989 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
994 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
1002 /****************************************************************************
1003 Function to do the mapping between the long architecture name and
1005 ****************************************************************************/
1007 const char *get_short_archi(const char *long_archi)
1011 DEBUG(107,("Getting architecture dependant directory\n"));
1014 } while ( (archi_table[i].long_archi!=NULL ) &&
1015 StrCaseCmp(long_archi, archi_table[i].long_archi) );
1017 if (archi_table[i].long_archi==NULL) {
1018 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1022 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1024 DEBUGADD(108,("index: [%d]\n", i));
1025 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1026 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1028 return archi_table[i].short_archi;
1031 /****************************************************************************
1032 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1033 There are two case to be covered here: PE (Portable Executable) and NE (New
1034 Executable) files. Both files support the same INFO structure, but PE files
1035 store the signature in unicode, and NE files store it as !unicode.
1036 returns -1 on error, 1 on version info found, and 0 on no version info found.
1037 ****************************************************************************/
1039 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1045 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1046 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1047 fname, DOS_HEADER_SIZE));
1051 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1052 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1053 fname, (unsigned long)byte_count));
1054 goto no_version_info;
1057 /* Is this really a DOS header? */
1058 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1059 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1060 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1061 goto no_version_info;
1064 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1065 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1066 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1068 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1069 goto no_version_info;
1072 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1073 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1074 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1075 fname, (unsigned long)byte_count));
1076 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1077 goto no_version_info;
1080 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1081 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1082 unsigned int num_sections;
1083 unsigned int section_table_bytes;
1085 /* Just skip over optional header to get to section table */
1086 if (SMB_VFS_LSEEK(fsp,
1087 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1088 SEEK_CUR) == (SMB_OFF_T)-1) {
1089 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1094 /* get the section table */
1095 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1096 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1097 if (section_table_bytes == 0)
1101 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1102 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1103 fname, section_table_bytes));
1107 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1108 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1109 fname, (unsigned long)byte_count));
1113 /* Iterate the section table looking for the resource section ".rsrc" */
1114 for (i = 0; i < num_sections; i++) {
1115 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1117 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1118 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1119 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1121 if (section_bytes == 0)
1125 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1126 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1127 fname, section_bytes));
1131 /* Seek to the start of the .rsrc section info */
1132 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1133 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1138 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1139 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1140 fname, (unsigned long)byte_count));
1144 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1147 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1148 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1149 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1150 /* Align to next long address */
1151 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1153 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1154 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1155 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1157 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1158 fname, *major, *minor,
1159 (*major>>16)&0xffff, *major&0xffff,
1160 (*minor>>16)&0xffff, *minor&0xffff));
1169 /* Version info not found, fall back to origin date/time */
1170 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1174 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1175 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1176 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1177 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1178 /* At this point, we assume the file is in error. It still could be somthing
1179 * else besides a NE file, but it unlikely at this point. */
1183 /* Allocate a bit more space to speed up things */
1185 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1186 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1187 fname, PE_HEADER_SIZE));
1191 /* This is a HACK! I got tired of trying to sort through the messy
1192 * 'NE' file format. If anyone wants to clean this up please have at
1193 * it, but this works. 'NE' files will eventually fade away. JRR */
1194 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1195 /* Cover case that should not occur in a well formed 'NE' .dll file */
1196 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1198 for(i=0; i<byte_count; i++) {
1199 /* Fast skip past data that can't possibly match */
1200 if (buf[i] != 'V') continue;
1202 /* Potential match data crosses buf boundry, move it to beginning
1203 * of buf, and fill the buf with as much as it will hold. */
1204 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1207 memcpy(buf, &buf[i], byte_count-i);
1208 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1209 (byte_count-i))) < 0) {
1211 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1216 byte_count = bc + (byte_count - i);
1217 if (byte_count<VS_VERSION_INFO_SIZE) break;
1222 /* Check that the full signature string and the magic number that
1223 * follows exist (not a perfect solution, but the chances that this
1224 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1225 * twice, as it is simpler to read the code. */
1226 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1227 /* Compute skip alignment to next long address */
1228 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1229 sizeof(VS_SIGNATURE)) & 3;
1230 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1232 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1233 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1234 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1235 fname, *major, *minor,
1236 (*major>>16)&0xffff, *major&0xffff,
1237 (*minor>>16)&0xffff, *minor&0xffff));
1244 /* Version info not found, fall back to origin date/time */
1245 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1250 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1251 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1252 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1263 /****************************************************************************
1264 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1265 share one or more files. During the MS installation process files are checked
1266 to insure that only a newer version of a shared file is installed over an
1267 older version. There are several possibilities for this comparison. If there
1268 is no previous version, the new one is newer (obviously). If either file is
1269 missing the version info structure, compare the creation date (on Unix use
1270 the modification date). Otherwise chose the numerically larger version number.
1271 ****************************************************************************/
1273 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1275 bool use_version = true;
1279 time_t new_create_time;
1283 time_t old_create_time;
1285 struct smb_filename *smb_fname = NULL;
1286 files_struct *fsp = NULL;
1292 SET_STAT_INVALID(st);
1293 new_create_time = (time_t)0;
1294 old_create_time = (time_t)0;
1296 /* Get file version info (if available) for previous file (if it exists) */
1297 status = driver_unix_convert(conn, old_file, &smb_fname);
1298 if (!NT_STATUS_IS_OK(status)) {
1302 status = SMB_VFS_CREATE_FILE(
1305 0, /* root_dir_fid */
1306 smb_fname, /* fname */
1307 FILE_GENERIC_READ, /* access_mask */
1308 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1309 FILE_OPEN, /* create_disposition*/
1310 0, /* create_options */
1311 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1312 INTERNAL_OPEN_ONLY, /* oplock_request */
1313 0, /* allocation_size */
1314 0, /* private_flags */
1320 if (!NT_STATUS_IS_OK(status)) {
1321 /* Old file not found, so by definition new file is in fact newer */
1322 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
1323 "errno = %d\n", smb_fname_str_dbg(smb_fname),
1329 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1335 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1337 use_version = false;
1338 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1341 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1342 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1343 (long)old_create_time));
1346 close_file(NULL, fsp, NORMAL_CLOSE);
1349 /* Get file version info (if available) for new file */
1350 status = driver_unix_convert(conn, new_file, &smb_fname);
1351 if (!NT_STATUS_IS_OK(status)) {
1355 status = SMB_VFS_CREATE_FILE(
1358 0, /* root_dir_fid */
1359 smb_fname, /* fname */
1360 FILE_GENERIC_READ, /* access_mask */
1361 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1362 FILE_OPEN, /* create_disposition*/
1363 0, /* create_options */
1364 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1365 INTERNAL_OPEN_ONLY, /* oplock_request */
1366 0, /* allocation_size */
1367 0, /* private_flags */
1373 if (!NT_STATUS_IS_OK(status)) {
1374 /* New file not found, this shouldn't occur if the caller did its job */
1375 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
1376 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
1380 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1386 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1388 use_version = false;
1389 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1392 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1393 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1394 (long)new_create_time));
1397 close_file(NULL, fsp, NORMAL_CLOSE);
1400 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1401 /* Compare versions and choose the larger version number */
1402 if (new_major > old_major ||
1403 (new_major == old_major && new_minor > old_minor)) {
1405 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1410 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1416 /* Compare modification time/dates and choose the newest time/date */
1417 if (new_create_time > old_create_time) {
1418 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1423 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1431 close_file(NULL, fsp, NORMAL_CLOSE);
1434 TALLOC_FREE(smb_fname);
1438 /****************************************************************************
1439 Determine the correct cVersion associated with an architecture and driver
1440 ****************************************************************************/
1441 static uint32 get_correct_cversion(struct pipes_struct *p,
1442 const char *architecture,
1443 const char *driverpath_in,
1448 struct smb_filename *smb_fname = NULL;
1449 char *driverpath = NULL;
1450 files_struct *fsp = NULL;
1451 connection_struct *conn = NULL;
1454 fstring printdollar;
1455 int printdollar_snum;
1457 *perr = WERR_INVALID_PARAM;
1459 /* If architecture is Windows 95/98/ME, the version is always 0. */
1460 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1461 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1466 /* If architecture is Windows x64, the version is always 3. */
1467 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1468 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1473 fstrcpy(printdollar, "print$");
1475 printdollar_snum = find_service(printdollar);
1476 if (printdollar_snum == -1) {
1477 *perr = WERR_NO_SUCH_SHARE;
1481 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1482 lp_pathname(printdollar_snum),
1483 p->server_info, &oldcwd);
1484 if (!NT_STATUS_IS_OK(nt_status)) {
1485 DEBUG(0,("get_correct_cversion: create_conn_struct "
1486 "returned %s\n", nt_errstr(nt_status)));
1487 *perr = ntstatus_to_werror(nt_status);
1491 /* Open the driver file (Portable Executable format) and determine the
1492 * deriver the cversion. */
1493 driverpath = talloc_asprintf(talloc_tos(),
1502 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
1503 if (!NT_STATUS_IS_OK(nt_status)) {
1504 *perr = ntstatus_to_werror(nt_status);
1508 nt_status = vfs_file_exist(conn, smb_fname);
1509 if (!NT_STATUS_IS_OK(nt_status)) {
1510 *perr = WERR_BADFILE;
1514 status = SMB_VFS_CREATE_FILE(
1517 0, /* root_dir_fid */
1518 smb_fname, /* fname */
1519 FILE_GENERIC_READ, /* access_mask */
1520 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1521 FILE_OPEN, /* create_disposition*/
1522 0, /* create_options */
1523 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1524 INTERNAL_OPEN_ONLY, /* oplock_request */
1525 0, /* private_flags */
1526 0, /* allocation_size */
1532 if (!NT_STATUS_IS_OK(status)) {
1533 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1534 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1535 *perr = WERR_ACCESS_DENIED;
1542 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1543 if (ret == -1) goto error_exit;
1546 DEBUG(6,("get_correct_cversion: Version info not "
1548 smb_fname_str_dbg(smb_fname)));
1553 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1554 * for more details. Version in this case is not just the version of the
1555 * file, but the version in the sense of kernal mode (2) vs. user mode
1556 * (3) drivers. Other bits of the version fields are the version info.
1559 cversion = major & 0x0000ffff;
1561 case 2: /* WinNT drivers */
1562 case 3: /* Win2K drivers */
1566 DEBUG(6,("get_correct_cversion: cversion "
1567 "invalid [%s] cversion = %d\n",
1568 smb_fname_str_dbg(smb_fname),
1573 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1574 " = 0x%x minor = 0x%x\n",
1575 smb_fname_str_dbg(smb_fname), major, minor));
1578 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1579 smb_fname_str_dbg(smb_fname), cversion));
1586 TALLOC_FREE(smb_fname);
1588 close_file(NULL, fsp, NORMAL_CLOSE);
1591 vfs_ChDir(conn, oldcwd);
1594 if (cversion != -1) {
1600 /****************************************************************************
1601 ****************************************************************************/
1603 #define strip_driver_path(_mem_ctx, _element) do { \
1604 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1605 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1606 W_ERROR_HAVE_NO_MEMORY((_element)); \
1610 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1611 struct pipes_struct *rpc_pipe,
1612 const char *architecture,
1613 const char **driver_path,
1614 const char **data_file,
1615 const char **config_file,
1616 const char **help_file,
1617 struct spoolss_StringArray *dependent_files,
1620 const char *short_architecture;
1625 if (!*driver_path || !*data_file || !*config_file) {
1626 return WERR_INVALID_PARAM;
1629 /* clean up the driver name.
1630 * we can get .\driver.dll
1631 * or worse c:\windows\system\driver.dll !
1633 /* using an intermediate string to not have overlaping memcpy()'s */
1635 strip_driver_path(mem_ctx, *driver_path);
1636 strip_driver_path(mem_ctx, *data_file);
1637 strip_driver_path(mem_ctx, *config_file);
1639 strip_driver_path(mem_ctx, *help_file);
1642 if (dependent_files && dependent_files->string) {
1643 for (i=0; dependent_files->string[i]; i++) {
1644 strip_driver_path(mem_ctx, dependent_files->string[i]);
1648 short_architecture = get_short_archi(architecture);
1649 if (!short_architecture) {
1650 return WERR_UNKNOWN_PRINTER_DRIVER;
1653 /* jfm:7/16/2000 the client always sends the cversion=0.
1654 * The server should check which version the driver is by reading
1655 * the PE header of driver->driverpath.
1657 * For Windows 95/98 the version is 0 (so the value sent is correct)
1658 * For Windows NT (the architecture doesn't matter)
1659 * NT 3.1: cversion=0
1660 * NT 3.5/3.51: cversion=1
1665 *version = get_correct_cversion(rpc_pipe, short_architecture,
1666 *driver_path, &err);
1667 if (*version == -1) {
1674 /****************************************************************************
1675 ****************************************************************************/
1677 WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe,
1678 struct spoolss_AddDriverInfoCtr *r)
1682 return clean_up_driver_struct_level(r, rpc_pipe,
1683 r->info.info3->architecture,
1684 &r->info.info3->driver_path,
1685 &r->info.info3->data_file,
1686 &r->info.info3->config_file,
1687 &r->info.info3->help_file,
1688 r->info.info3->dependent_files,
1689 &r->info.info3->version);
1691 return clean_up_driver_struct_level(r, rpc_pipe,
1692 r->info.info6->architecture,
1693 &r->info.info6->driver_path,
1694 &r->info.info6->data_file,
1695 &r->info.info6->config_file,
1696 &r->info.info6->help_file,
1697 r->info.info6->dependent_files,
1698 &r->info.info6->version);
1700 return WERR_NOT_SUPPORTED;
1704 /****************************************************************************
1705 This function sucks and should be replaced. JRA.
1706 ****************************************************************************/
1708 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1709 const struct spoolss_AddDriverInfo6 *src)
1711 dst->version = src->version;
1713 dst->driver_name = src->driver_name;
1714 dst->architecture = src->architecture;
1715 dst->driver_path = src->driver_path;
1716 dst->data_file = src->data_file;
1717 dst->config_file = src->config_file;
1718 dst->help_file = src->help_file;
1719 dst->monitor_name = src->monitor_name;
1720 dst->default_datatype = src->default_datatype;
1721 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1722 dst->dependent_files = src->dependent_files;
1725 /****************************************************************************
1726 This function sucks and should be replaced. JRA.
1727 ****************************************************************************/
1729 static void convert_level_8_to_level3(TALLOC_CTX *mem_ctx,
1730 struct spoolss_AddDriverInfo3 *dst,
1731 const struct spoolss_DriverInfo8 *src)
1733 dst->version = src->version;
1734 dst->driver_name = src->driver_name;
1735 dst->architecture = src->architecture;
1736 dst->driver_path = src->driver_path;
1737 dst->data_file = src->data_file;
1738 dst->config_file = src->config_file;
1739 dst->help_file = src->help_file;
1740 dst->monitor_name = src->monitor_name;
1741 dst->default_datatype = src->default_datatype;
1742 if (src->dependent_files) {
1743 dst->dependent_files = talloc_zero(mem_ctx, struct spoolss_StringArray);
1744 if (!dst->dependent_files) return;
1745 dst->dependent_files->string = src->dependent_files;
1747 dst->dependent_files = NULL;
1751 /****************************************************************************
1752 ****************************************************************************/
1754 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1755 connection_struct *conn,
1756 const char *driver_file,
1757 const char *short_architecture,
1758 uint32_t driver_version,
1761 struct smb_filename *smb_fname_old = NULL;
1762 struct smb_filename *smb_fname_new = NULL;
1763 char *old_name = NULL;
1764 char *new_name = NULL;
1768 old_name = talloc_asprintf(mem_ctx, "%s/%s",
1769 short_architecture, driver_file);
1770 W_ERROR_HAVE_NO_MEMORY(old_name);
1772 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1773 short_architecture, driver_version, driver_file);
1774 if (new_name == NULL) {
1775 TALLOC_FREE(old_name);
1779 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1781 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1782 if (!NT_STATUS_IS_OK(status)) {
1787 /* Setup a synthetic smb_filename struct */
1788 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
1789 if (!smb_fname_new) {
1794 smb_fname_new->base_name = new_name;
1796 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1797 "'%s'\n", smb_fname_old->base_name,
1798 smb_fname_new->base_name));
1800 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1801 OPENX_FILE_EXISTS_TRUNCATE |
1802 OPENX_FILE_CREATE_IF_NOT_EXIST,
1805 if (!NT_STATUS_IS_OK(status)) {
1806 DEBUG(0,("move_driver_file_to_download_area: Unable "
1807 "to rename [%s] to [%s]: %s\n",
1808 smb_fname_old->base_name, new_name,
1809 nt_errstr(status)));
1810 ret = WERR_ACCESS_DENIED;
1817 TALLOC_FREE(smb_fname_old);
1818 TALLOC_FREE(smb_fname_new);
1822 WERROR move_driver_to_download_area(struct pipes_struct *p,
1823 struct spoolss_AddDriverInfoCtr *r,
1826 struct spoolss_AddDriverInfo3 *driver;
1827 struct spoolss_AddDriverInfo3 converted_driver;
1828 const char *short_architecture;
1829 struct smb_filename *smb_dname = NULL;
1830 char *new_dir = NULL;
1831 connection_struct *conn = NULL;
1834 TALLOC_CTX *ctx = talloc_tos();
1837 fstring printdollar;
1838 int printdollar_snum;
1844 driver = r->info.info3;
1847 convert_level_6_to_level3(&converted_driver, r->info.info6);
1848 driver = &converted_driver;
1851 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1852 return WERR_UNKNOWN_LEVEL;
1855 short_architecture = get_short_archi(driver->architecture);
1856 if (!short_architecture) {
1857 return WERR_UNKNOWN_PRINTER_DRIVER;
1860 fstrcpy(printdollar, "print$");
1862 printdollar_snum = find_service(printdollar);
1863 if (printdollar_snum == -1) {
1864 *perr = WERR_NO_SUCH_SHARE;
1865 return WERR_NO_SUCH_SHARE;
1868 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1869 lp_pathname(printdollar_snum),
1870 p->server_info, &oldcwd);
1871 if (!NT_STATUS_IS_OK(nt_status)) {
1872 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1873 "returned %s\n", nt_errstr(nt_status)));
1874 *perr = ntstatus_to_werror(nt_status);
1878 new_dir = talloc_asprintf(ctx,
1886 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1887 if (!NT_STATUS_IS_OK(nt_status)) {
1892 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1894 create_directory(conn, NULL, smb_dname);
1896 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1897 * listed for this driver which has already been moved, skip it (note:
1898 * drivers may list the same file name several times. Then check if the
1899 * file already exists in archi\version\, if so, check that the version
1900 * info (or time stamps if version info is unavailable) is newer (or the
1901 * date is later). If it is, move it to archi\version\filexxx.yyy.
1902 * Otherwise, delete the file.
1904 * If a file is not moved to archi\version\ because of an error, all the
1905 * rest of the 'unmoved' driver files are removed from archi\. If one or
1906 * more of the driver's files was already moved to archi\version\, it
1907 * potentially leaves the driver in a partially updated state. Version
1908 * trauma will most likely occur if an client attempts to use any printer
1909 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1910 * done is appropriate... later JRR
1913 DEBUG(5,("Moving files now !\n"));
1915 if (driver->driver_path && strlen(driver->driver_path)) {
1917 *perr = move_driver_file_to_download_area(ctx,
1919 driver->driver_path,
1923 if (!W_ERROR_IS_OK(*perr)) {
1924 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1931 if (driver->data_file && strlen(driver->data_file)) {
1932 if (!strequal(driver->data_file, driver->driver_path)) {
1934 *perr = move_driver_file_to_download_area(ctx,
1940 if (!W_ERROR_IS_OK(*perr)) {
1941 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1949 if (driver->config_file && strlen(driver->config_file)) {
1950 if (!strequal(driver->config_file, driver->driver_path) &&
1951 !strequal(driver->config_file, driver->data_file)) {
1953 *perr = move_driver_file_to_download_area(ctx,
1955 driver->config_file,
1959 if (!W_ERROR_IS_OK(*perr)) {
1960 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1968 if (driver->help_file && strlen(driver->help_file)) {
1969 if (!strequal(driver->help_file, driver->driver_path) &&
1970 !strequal(driver->help_file, driver->data_file) &&
1971 !strequal(driver->help_file, driver->config_file)) {
1973 *perr = move_driver_file_to_download_area(ctx,
1979 if (!W_ERROR_IS_OK(*perr)) {
1980 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1988 if (driver->dependent_files && driver->dependent_files->string) {
1989 for (i=0; driver->dependent_files->string[i]; i++) {
1990 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1991 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1992 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1993 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1995 for (j=0; j < i; j++) {
1996 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
2001 *perr = move_driver_file_to_download_area(ctx,
2003 driver->dependent_files->string[i],
2007 if (!W_ERROR_IS_OK(*perr)) {
2008 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
2019 TALLOC_FREE(smb_dname);
2022 vfs_ChDir(conn, oldcwd);
2026 if (W_ERROR_EQUAL(*perr, WERR_OK)) {
2030 return WERR_UNKNOWN_PRINTER_DRIVER;
2035 /****************************************************************************
2036 ****************************************************************************/
2038 static uint32 add_a_printer_driver_3(struct spoolss_AddDriverInfo3 *driver)
2040 TALLOC_CTX *ctx = talloc_tos();
2042 const char *architecture;
2043 char *directory = NULL;
2049 architecture = get_short_archi(driver->architecture);
2050 if (!architecture) {
2054 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2055 * \\server is added in the rpc server layer.
2056 * It does make sense to NOT store the server's name in the printer TDB.
2059 directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
2060 architecture, driver->version);
2065 #define gen_full_driver_unc_path(ctx, directory, file) \
2067 if (file && strlen(file)) { \
2068 file = talloc_asprintf(ctx, "%s%s", directory, file); \
2070 file = talloc_strdup(ctx, ""); \
2073 return (uint32_t)-1; \
2077 /* .inf files do not always list a file for each of the four standard files.
2078 * Don't prepend a path to a null filename, or client claims:
2079 * "The server on which the printer resides does not have a suitable
2080 * <printer driver name> printer driver installed. Click OK if you
2081 * wish to install the driver on your local machine."
2084 gen_full_driver_unc_path(ctx, directory, driver->driver_path);
2085 gen_full_driver_unc_path(ctx, directory, driver->data_file);
2086 gen_full_driver_unc_path(ctx, directory, driver->config_file);
2087 gen_full_driver_unc_path(ctx, directory, driver->help_file);
2089 if (driver->dependent_files && driver->dependent_files->string) {
2090 for (i=0; driver->dependent_files->string[i]; i++) {
2091 gen_full_driver_unc_path(ctx, directory,
2092 driver->dependent_files->string[i]);
2096 key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
2097 architecture, driver->version, driver->driver_name);
2102 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
2109 len += tdb_pack(buf+len, buflen-len, "dffffffff",
2111 driver->driver_name,
2112 driver->architecture,
2113 driver->driver_path,
2115 driver->config_file,
2117 driver->monitor_name ? driver->monitor_name : "",
2118 driver->default_datatype ? driver->default_datatype : "");
2120 if (driver->dependent_files && driver->dependent_files->string) {
2121 for (i=0; driver->dependent_files->string[i]; i++) {
2122 len += tdb_pack(buf+len, buflen-len, "f",
2123 driver->dependent_files->string[i]);
2127 if (len != buflen) {
2128 buf = (uint8 *)SMB_REALLOC(buf, len);
2130 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2141 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2145 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2151 /****************************************************************************
2152 ****************************************************************************/
2154 static uint32_t add_a_printer_driver_8(struct spoolss_DriverInfo8 *driver)
2156 TALLOC_CTX *mem_ctx = talloc_new(talloc_tos());
2157 struct spoolss_AddDriverInfo3 info3;
2160 convert_level_8_to_level3(mem_ctx, &info3, driver);
2162 ret = add_a_printer_driver_3(&info3);
2163 talloc_free(mem_ctx);
2168 /****************************************************************************
2169 ****************************************************************************/
2171 static WERROR get_a_printer_driver_3_default(TALLOC_CTX *mem_ctx,
2172 struct spoolss_DriverInfo3 *info,
2173 const char *driver, const char *arch)
2175 info->driver_name = talloc_strdup(mem_ctx, driver);
2176 if (!info->driver_name) {
2180 info->default_datatype = talloc_strdup(mem_ctx, "RAW");
2181 if (!info->default_datatype) {
2185 info->driver_path = talloc_strdup(mem_ctx, "");
2186 info->data_file = talloc_strdup(mem_ctx, "");
2187 info->config_file = talloc_strdup(mem_ctx, "");
2188 info->help_file = talloc_strdup(mem_ctx, "");
2189 if (!info->driver_path || !info->data_file || !info->config_file || !info->help_file) {
2196 /****************************************************************************
2197 ****************************************************************************/
2199 static WERROR get_a_printer_driver_3(TALLOC_CTX *mem_ctx,
2200 struct spoolss_DriverInfo3 *driver,
2201 const char *drivername, const char *arch,
2205 const char *architecture;
2209 fstring name, driverpath, environment, datafile, configfile, helpfile, monitorname, defaultdatatype;
2211 architecture = get_short_archi(arch);
2212 if ( !architecture ) {
2213 return WERR_UNKNOWN_PRINTER_DRIVER;
2216 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2218 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2221 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2223 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
2224 architecture, version, drivername) < 0) {
2228 dbuf = tdb_fetch_bystring(tdb_drivers, key);
2231 return WERR_UNKNOWN_PRINTER_DRIVER;
2234 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2245 driver->driver_name = talloc_strdup(mem_ctx, name);
2246 driver->architecture = talloc_strdup(mem_ctx, environment);
2247 driver->driver_path = talloc_strdup(mem_ctx, driverpath);
2248 driver->data_file = talloc_strdup(mem_ctx, datafile);
2249 driver->config_file = talloc_strdup(mem_ctx, configfile);
2250 driver->help_file = talloc_strdup(mem_ctx, helpfile);
2251 driver->monitor_name = talloc_strdup(mem_ctx, monitorname);
2252 driver->default_datatype = talloc_strdup(mem_ctx, defaultdatatype);
2256 while (len < dbuf.dsize) {
2260 driver->dependent_files = talloc_realloc(mem_ctx, driver->dependent_files, const char *, i+2);
2261 if (!driver->dependent_files ) {
2262 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2266 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2269 driver->dependent_files[i] = talloc_strdup(mem_ctx, file);
2274 if (driver->dependent_files)
2275 driver->dependent_files[i] = NULL;
2277 SAFE_FREE(dbuf.dptr);
2280 if (len != dbuf.dsize) {
2281 return get_a_printer_driver_3_default(mem_ctx, driver, drivername, arch);
2287 /****************************************************************************
2288 ****************************************************************************/
2289 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2293 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2298 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2299 nt_devmode->devicename,
2300 nt_devmode->formname,
2302 nt_devmode->specversion,
2303 nt_devmode->driverversion,
2305 nt_devmode->driverextra,
2306 nt_devmode->orientation,
2307 nt_devmode->papersize,
2308 nt_devmode->paperlength,
2309 nt_devmode->paperwidth,
2312 nt_devmode->defaultsource,
2313 nt_devmode->printquality,
2316 nt_devmode->yresolution,
2317 nt_devmode->ttoption,
2318 nt_devmode->collate,
2319 nt_devmode->logpixels,
2322 nt_devmode->bitsperpel,
2323 nt_devmode->pelswidth,
2324 nt_devmode->pelsheight,
2325 nt_devmode->displayflags,
2326 nt_devmode->displayfrequency,
2327 nt_devmode->icmmethod,
2328 nt_devmode->icmintent,
2329 nt_devmode->mediatype,
2330 nt_devmode->dithertype,
2331 nt_devmode->reserved1,
2332 nt_devmode->reserved2,
2333 nt_devmode->panningwidth,
2334 nt_devmode->panningheight,
2335 nt_devmode->nt_dev_private);
2337 if (nt_devmode->nt_dev_private) {
2338 len += tdb_pack(buf+len, buflen-len, "B",
2339 nt_devmode->driverextra,
2340 nt_devmode->nt_dev_private);
2343 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2348 /****************************************************************************
2349 Pack all values in all printer keys
2350 ***************************************************************************/
2352 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2356 struct regval_blob *val;
2357 struct regval_ctr *val_ctr;
2364 /* loop over all keys */
2366 for ( i=0; i<data->num_keys; i++ ) {
2367 val_ctr = data->keys[i].values;
2368 num_values = regval_ctr_numvals( val_ctr );
2370 /* pack the keyname followed by a empty value */
2372 len += tdb_pack(buf+len, buflen-len, "pPdB",
2373 &data->keys[i].name,
2379 /* now loop over all values */
2381 for ( j=0; j<num_values; j++ ) {
2382 /* pathname should be stored as <key>\<value> */
2384 val = regval_ctr_specific_value( val_ctr, j );
2385 if (asprintf(&path, "%s\\%s",
2387 regval_name(val)) < 0) {
2391 len += tdb_pack(buf+len, buflen-len, "pPdB",
2396 regval_data_p(val) );
2398 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2406 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2412 /****************************************************************************
2413 Delete a printer - this just deletes the printer info file, any open
2414 handles are not affected.
2415 ****************************************************************************/
2417 uint32 del_a_printer(const char *sharename)
2420 char *printdb_path = NULL;
2421 TALLOC_CTX *ctx = talloc_tos();
2423 kbuf = make_printer_tdbkey(ctx, sharename);
2424 tdb_delete(tdb_printers, kbuf);
2426 kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2427 tdb_delete(tdb_printers, kbuf);
2429 close_all_print_db();
2431 if (geteuid() == sec_initial_uid()) {
2432 if (asprintf(&printdb_path, "%s%s.tdb",
2433 cache_path("printing/"),
2437 unlink(printdb_path);
2438 SAFE_FREE(printdb_path);
2444 /****************************************************************************
2445 ****************************************************************************/
2446 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2452 TDB_DATA kbuf, dbuf;
2455 * in addprinter: no servername and the printer is the name
2456 * in setprinter: servername is \\server
2457 * and printer is \\server\\printer
2459 * Samba manages only local printers.
2460 * we currently don't support things like i
2461 * path=\\other_server\printer
2463 * We only store the printername, not \\server\printername
2466 if ( info->servername[0] != '\0' ) {
2467 trim_string(info->printername, info->servername, NULL);
2468 trim_char(info->printername, '\\', '\0');
2469 info->servername[0]='\0';
2473 * JFM: one day I'll forget.
2474 * below that's info->portname because that's the SAMBA sharename
2475 * and I made NT 'thinks' it's the portname
2476 * the info->sharename is the thing you can name when you add a printer
2477 * that's the short-name when you create shared printer for 95/98
2478 * So I've made a limitation in SAMBA: you can only have 1 printer model
2479 * behind a SAMBA share.
2487 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2490 info->default_priority,
2507 info->printprocessor,
2511 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2512 retlen = pack_values( info->data, buf+len, buflen-len );
2519 if (buflen != len) {
2520 buf = (uint8 *)SMB_REALLOC(buf, len);
2522 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2530 kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2535 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2538 if (!W_ERROR_IS_OK(ret))
2539 DEBUG(8, ("error updating printer to tdb on disk\n"));
2543 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2544 info->sharename, info->drivername, info->portname, len));
2549 /****************************************************************************
2550 Create and allocate a default devicemode.
2551 ****************************************************************************/
2553 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
2554 const char *devicename,
2555 struct spoolss_DeviceMode **devmode)
2557 struct spoolss_DeviceMode *dm;
2560 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2565 dname = talloc_asprintf(dm, "%s", devicename);
2566 if (dname == NULL) {
2569 if (strlen(dname) > MAXDEVICENAME) {
2570 dname[MAXDEVICENAME] = '\0';
2572 dm->devicename = dname;
2574 dm->formname = talloc_strdup(dm, "Letter");
2575 if (dm->formname == NULL) {
2579 dm->specversion = DMSPEC_NT4_AND_ABOVE;
2580 dm->driverversion = 0x0400;
2582 dm->__driverextra_length = 0;
2583 dm->fields = DEVMODE_FORMNAME |
2585 DEVMODE_PRINTQUALITY |
2586 DEVMODE_DEFAULTSOURCE |
2590 DEVMODE_ORIENTATION;
2591 dm->orientation = DMORIENT_PORTRAIT;
2592 dm->papersize = DMPAPER_LETTER;
2593 dm->paperlength = 0;
2597 dm->defaultsource = DMBIN_FORMSOURCE;
2598 dm->printquality = DMRES_HIGH; /* 0x0258 */
2599 dm->color = DMRES_MONOCHROME;
2600 dm->duplex = DMDUP_SIMPLEX;
2601 dm->yresolution = 0;
2602 dm->ttoption = DMTT_SUBDEV;
2603 dm->collate = DMCOLLATE_FALSE;
2613 dm->displayflags = 0;
2614 dm->displayfrequency = 0;
2617 dm->panningwidth = 0;
2618 dm->panningheight = 0;
2620 dm->driverextra_data.data = NULL;
2621 dm->driverextra_data.length = 0;
2627 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
2628 struct spoolss_security_descriptor **secdesc)
2630 struct security_ace ace[5]; /* max number of ace entries */
2633 struct security_acl *psa = NULL;
2634 struct security_descriptor *psd = NULL;
2635 struct dom_sid adm_sid;
2638 /* Create an ACE where Everyone is allowed to print */
2640 sa = PRINTER_ACE_PRINT;
2641 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2642 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2644 /* Add the domain admins group if we are a DC */
2647 struct dom_sid domadmins_sid;
2649 sid_compose(&domadmins_sid, get_global_sam_sid(),
2652 sa = PRINTER_ACE_FULL_CONTROL;
2653 init_sec_ace(&ace[i++], &domadmins_sid,
2654 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2655 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2656 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2657 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2659 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
2660 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
2662 sa = PRINTER_ACE_FULL_CONTROL;
2663 init_sec_ace(&ace[i++], &adm_sid,
2664 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2665 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2666 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2667 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2670 /* add BUILTIN\Administrators as FULL CONTROL */
2672 sa = PRINTER_ACE_FULL_CONTROL;
2673 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2674 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2675 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2676 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2677 SEC_ACE_TYPE_ACCESS_ALLOWED,
2678 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2680 /* Make the security descriptor owned by the BUILTIN\Administrators */
2682 /* The ACL revision number in rpc_secdesc.h differs from the one
2683 created by NT when setting ACE entries in printer
2684 descriptors. NT4 complains about the property being edited by a
2687 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
2688 psd = make_sec_desc(mem_ctx,
2690 SEC_DESC_SELF_RELATIVE,
2691 &global_sid_Builtin_Administrators,
2692 &global_sid_Builtin_Administrators,
2699 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2703 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2704 (unsigned int)sd_size));
2711 /****************************************************************************
2712 Malloc and return an NT devicemode.
2713 ****************************************************************************/
2715 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2718 char adevice[MAXDEVICENAME];
2719 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2721 if (nt_devmode == NULL) {
2722 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2726 ZERO_STRUCTP(nt_devmode);
2728 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2729 fstrcpy(nt_devmode->devicename, adevice);
2731 fstrcpy(nt_devmode->formname, "Letter");
2733 nt_devmode->specversion = DMSPEC_NT4_AND_ABOVE;
2734 nt_devmode->driverversion = 0x0400;
2735 nt_devmode->size = 0x00DC;
2736 nt_devmode->driverextra = 0x0000;
2737 nt_devmode->fields = DEVMODE_FORMNAME |
2739 DEVMODE_PRINTQUALITY |
2740 DEVMODE_DEFAULTSOURCE |
2744 DEVMODE_ORIENTATION;
2745 nt_devmode->orientation = DMORIENT_PORTRAIT;
2746 nt_devmode->papersize = DMPAPER_LETTER;
2747 nt_devmode->paperlength = 0;
2748 nt_devmode->paperwidth = 0;
2749 nt_devmode->scale = 0x64;
2750 nt_devmode->copies = 1;
2751 nt_devmode->defaultsource = DMBIN_FORMSOURCE;
2752 nt_devmode->printquality = DMRES_HIGH; /* 0x0258 */
2753 nt_devmode->color = DMRES_MONOCHROME;
2754 nt_devmode->duplex = DMDUP_SIMPLEX;
2755 nt_devmode->yresolution = 0;
2756 nt_devmode->ttoption = DMTT_SUBDEV;
2757 nt_devmode->collate = DMCOLLATE_FALSE;
2758 nt_devmode->icmmethod = 0;
2759 nt_devmode->icmintent = 0;
2760 nt_devmode->mediatype = 0;
2761 nt_devmode->dithertype = 0;
2763 /* non utilisés par un driver d'imprimante */
2764 nt_devmode->logpixels = 0;
2765 nt_devmode->bitsperpel = 0;
2766 nt_devmode->pelswidth = 0;
2767 nt_devmode->pelsheight = 0;
2768 nt_devmode->displayflags = 0;
2769 nt_devmode->displayfrequency = 0;
2770 nt_devmode->reserved1 = 0;
2771 nt_devmode->reserved2 = 0;
2772 nt_devmode->panningwidth = 0;
2773 nt_devmode->panningheight = 0;
2775 nt_devmode->nt_dev_private = NULL;
2779 /****************************************************************************
2780 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2781 ****************************************************************************/
2783 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2785 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2787 if(nt_devmode == NULL)
2790 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2792 SAFE_FREE(nt_devmode->nt_dev_private);
2793 SAFE_FREE(*devmode_ptr);
2796 /****************************************************************************
2797 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2798 ****************************************************************************/
2800 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2802 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2807 free_nt_devicemode(&info->devmode);
2809 TALLOC_FREE( *info_ptr );
2813 /****************************************************************************
2814 ****************************************************************************/
2815 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2819 NT_DEVICEMODE devmode;
2821 ZERO_STRUCT(devmode);
2823 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2825 if (!*nt_devmode) return len;
2827 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2831 &devmode.specversion,
2832 &devmode.driverversion,
2834 &devmode.driverextra,
2835 &devmode.orientation,
2837 &devmode.paperlength,
2838 &devmode.paperwidth,
2841 &devmode.defaultsource,
2842 &devmode.printquality,
2845 &devmode.yresolution,
2851 &devmode.bitsperpel,
2853 &devmode.pelsheight,
2854 &devmode.displayflags,
2855 &devmode.displayfrequency,
2859 &devmode.dithertype,
2862 &devmode.panningwidth,
2863 &devmode.panningheight,
2864 &devmode.nt_dev_private);
2866 if (devmode.nt_dev_private) {
2867 /* the len in tdb_unpack is an int value and
2868 * devmode.driverextra is only a short
2870 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2871 devmode.driverextra=(uint16)extra_len;
2873 /* check to catch an invalid TDB entry so we don't segfault */
2874 if (devmode.driverextra == 0) {
2875 devmode.nt_dev_private = NULL;
2879 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2881 SAFE_FREE(devmode.nt_dev_private);
2885 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2886 if (devmode.nt_dev_private)
2887 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2892 /****************************************************************************
2893 Allocate and initialize a new slot.
2894 ***************************************************************************/
2896 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2902 if ( !name || !data )
2905 /* allocate another slot in the NT_PRINTER_KEY array */
2907 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2908 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2914 key_index = data->num_keys;
2916 /* initialze new key */
2918 data->keys[key_index].name = talloc_strdup( data, name );
2920 werr = regval_ctr_init(data, &(data->keys[key_index].values));
2921 if (!W_ERROR_IS_OK(werr)) {
2927 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2932 /****************************************************************************
2933 search for a registry key name in the existing printer data
2934 ***************************************************************************/
2936 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2940 for ( i=0; i<data->num_keys; i++ ) {
2941 if ( strequal( data->keys[i].name, name ) ) {
2943 /* cleanup memory */
2945 TALLOC_FREE( data->keys[i].name );
2946 TALLOC_FREE( data->keys[i].values );
2948 /* if not the end of the array, move remaining elements down one slot */
2951 if ( data->num_keys && (i < data->num_keys) )
2952 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2959 return data->num_keys;
2962 /****************************************************************************
2963 search for a registry key name in the existing printer data
2964 ***************************************************************************/
2966 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2971 if ( !data || !name )
2974 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2976 /* loop over all existing keys */
2978 for ( i=0; i<data->num_keys; i++ ) {
2979 if ( strequal(data->keys[i].name, name) ) {
2980 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2990 /****************************************************************************
2991 ***************************************************************************/
2993 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2997 int num_subkeys = 0;
2999 fstring *subkeys_ptr = NULL;
3010 /* special case of asking for the top level printer data registry key names */
3012 if ( strlen(key) == 0 ) {
3013 for ( i=0; i<data->num_keys; i++ ) {
3015 /* found a match, so allocate space and copy the name */
3017 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3018 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3023 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
3030 /* asking for the subkeys of some key */
3031 /* subkey paths are stored in the key name using '\' as the delimiter */
3033 for ( i=0; i<data->num_keys; i++ ) {
3034 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
3036 /* if we found the exact key, then break */
3037 key_len = strlen( key );
3038 if ( strlen(data->keys[i].name) == key_len )
3041 /* get subkey path */
3043 p = data->keys[i].name + key_len;
3046 fstrcpy( subkeyname, p );
3047 if ( (p = strchr( subkeyname, '\\' )) )
3050 /* don't add a key more than once */
3052 for ( j=0; j<num_subkeys; j++ ) {
3053 if ( strequal( subkeys_ptr[j], subkeyname ) )
3057 if ( j != num_subkeys )
3060 /* found a match, so allocate space and copy the name */
3062 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3063 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3068 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
3074 /* return error if the key was not found */
3076 if ( i == data->num_keys ) {
3077 SAFE_FREE(subkeys_ptr);
3082 /* tag off the end */
3085 fstrcpy(subkeys_ptr[num_subkeys], "" );
3087 *subkeys = subkeys_ptr;
3093 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3096 regval_ctr_delvalue(ctr, val_name);
3097 regval_ctr_addvalue_sz(ctr, val_name, sz);
3100 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
3103 regval_ctr_delvalue(ctr, val_name);
3104 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
3105 (uint8 *) &dword, sizeof(dword));
3108 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
3111 uint8 bin_bool = (b ? 1 : 0);
3112 regval_ctr_delvalue(ctr, val_name);
3113 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
3114 (uint8 *) &bin_bool, sizeof(bin_bool));
3117 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3118 const char *multi_sz)
3125 regval_ctr_delvalue(ctr, val_name);
3126 regval_ctr_addvalue_multi_sz(ctr, val_name, a);
3129 /****************************************************************************
3130 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3132 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3133 * @return bool indicating success or failure
3134 ***************************************************************************/
3136 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
3138 struct regval_ctr *ctr = NULL;
3140 const char *dnssuffix;
3141 char *allocated_string = NULL;
3142 const char *ascii_str;
3145 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3146 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3147 ctr = info2->data->keys[i].values;
3149 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3150 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3152 /* we make the assumption that the netbios name is the same
3153 as the DNS name sinc ethe former will be what we used to
3156 dnssuffix = get_mydnsdomname(talloc_tos());
3157 if (dnssuffix && *dnssuffix) {
3158 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3160 fstrcpy( longname, global_myname() );
3163 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3165 if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3168 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3169 SAFE_FREE(allocated_string);
3171 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3172 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3173 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3174 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3175 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3176 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3177 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3178 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3179 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3181 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3182 (info2->attributes &
3183 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3185 switch (info2->attributes & 0x3) {
3187 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3190 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3193 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3196 ascii_str = "unknown";
3198 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3203 /*****************************************************************
3204 ****************************************************************/
3206 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3210 struct regval_ctr *ctr=NULL;
3212 /* find the DsSpooler key */
3213 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3214 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3215 ctr = info2->data->keys[i].values;
3217 regval_ctr_delvalue(ctr, "objectGUID");
3219 /* We used to store this as a REG_BINARY but that causes
3222 regval_ctr_addvalue_sz(ctr, "objectGUID",
3223 GUID_string(talloc_tos(), &guid));
3226 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3227 NT_PRINTER_INFO_LEVEL *printer)
3231 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3232 char *srv_dn_utf8, **srv_cn_utf8;
3235 const char *attrs[] = {"objectGUID", NULL};
3237 WERROR win_rc = WERR_OK;
3238 size_t converted_size;
3240 /* build the ads mods */
3241 ctx = talloc_init("nt_printer_publish_ads");
3246 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3248 /* figure out where to publish */
3249 ads_find_machine_acct(ads, &res, global_myname());
3251 /* We use ldap_get_dn here as we need the answer
3252 * in utf8 to call ldap_explode_dn(). JRA. */
3254 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3257 return WERR_SERVER_UNAVAILABLE;
3259 ads_msgfree(ads, res);
3260 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3263 ldap_memfree(srv_dn_utf8);
3264 return WERR_SERVER_UNAVAILABLE;
3266 /* Now convert to CH_UNIX. */
3267 if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3269 ldap_memfree(srv_dn_utf8);
3270 ldap_memfree(srv_cn_utf8);
3271 return WERR_SERVER_UNAVAILABLE;
3273 if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3275 ldap_memfree(srv_dn_utf8);
3276 ldap_memfree(srv_cn_utf8);
3277 TALLOC_FREE(srv_dn);
3278 return WERR_SERVER_UNAVAILABLE;
3281 ldap_memfree(srv_dn_utf8);
3282 ldap_memfree(srv_cn_utf8);
3284 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3285 if (!srv_cn_escaped) {
3287 return WERR_SERVER_UNAVAILABLE;
3289 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3290 if (!sharename_escaped) {
3291 SAFE_FREE(srv_cn_escaped);
3293 return WERR_SERVER_UNAVAILABLE;
3296 prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3298 SAFE_FREE(srv_cn_escaped);
3299 SAFE_FREE(sharename_escaped);
3301 mods = ads_init_mods(ctx);
3309 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3310 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3311 printer->info_2->sharename);
3314 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3315 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3317 for (i=0; mods[i] != 0; i++)
3319 mods[i] = (LDAPMod *)-1;
3320 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3323 if (!ADS_ERR_OK(ads_rc))
3324 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3326 /* retreive the guid and store it locally */
3327 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3329 ads_pull_guid(ads, res, &guid);
3330 ads_msgfree(ads, res);
3331 store_printer_guid(printer->info_2, guid);
3332 win_rc = mod_a_printer(printer, 2);
3339 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3340 NT_PRINTER_INFO_LEVEL *printer)
3343 LDAPMessage *res = NULL;
3344 char *prt_dn = NULL;
3346 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3348 /* remove the printer from the directory */
3349 ads_rc = ads_find_printer_on_server(ads, &res,
3350 printer->info_2->sharename, global_myname());
3352 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3353 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3355 ads_msgfree(ads, res);
3358 ads_rc = ads_del_dn(ads, prt_dn);
3359 TALLOC_FREE(prt_dn);
3363 ads_msgfree(ads, res);
3368 /****************************************************************************
3369 * Publish a printer in the directory
3371 * @param snum describing printer service
3372 * @return WERROR indicating status of publishing
3373 ***************************************************************************/
3375 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3378 ADS_STRUCT *ads = NULL;
3379 NT_PRINTER_INFO_LEVEL *printer = NULL;
3382 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3383 if (!W_ERROR_IS_OK(win_rc))
3387 case DSPRINT_PUBLISH:
3388 case DSPRINT_UPDATE:
3389 /* set the DsSpooler info and attributes */
3390 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3391 win_rc = WERR_NOMEM;
3395 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3397 case DSPRINT_UNPUBLISH:
3398 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3401 win_rc = WERR_NOT_SUPPORTED;
3405 win_rc = mod_a_printer(printer, 2);
3406 if (!W_ERROR_IS_OK(win_rc)) {
3407 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3411 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3413 DEBUG(3, ("ads_init() failed\n"));
3414 win_rc = WERR_SERVER_UNAVAILABLE;
3417 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3418 SAFE_FREE(ads->auth.password);
3419 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3422 /* ads_connect() will find the DC for us */
3423 ads_rc = ads_connect(ads);
3424 if (!ADS_ERR_OK(ads_rc)) {
3425 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3426 win_rc = WERR_ACCESS_DENIED;
3431 case DSPRINT_PUBLISH:
3432 case DSPRINT_UPDATE:
3433 win_rc = nt_printer_publish_ads(ads, printer);
3435 case DSPRINT_UNPUBLISH:
3436 win_rc = nt_printer_unpublish_ads(ads, printer);
3441 free_a_printer(&printer, 2);
3446 WERROR check_published_printers(void)
3449 ADS_STRUCT *ads = NULL;
3451 int n_services = lp_numservices();
3452 NT_PRINTER_INFO_LEVEL *printer = NULL;
3454 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3456 DEBUG(3, ("ads_init() failed\n"));
3457 return WERR_SERVER_UNAVAILABLE;
3459 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3460 SAFE_FREE(ads->auth.password);
3461 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3464 /* ads_connect() will find the DC for us */
3465 ads_rc = ads_connect(ads);
3466 if (!ADS_ERR_OK(ads_rc)) {
3467 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3469 ads_kdestroy("MEMORY:prtpub_cache");
3470 return WERR_ACCESS_DENIED;
3473 for (snum = 0; snum < n_services; snum++) {
3474 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3477 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3478 lp_servicename(snum))) &&
3479 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3480 nt_printer_publish_ads(ads, printer);
3482 free_a_printer(&printer, 2);
3486 ads_kdestroy("MEMORY:prtpub_cache");
3490 bool is_printer_published(Printer_entry *print_hnd, int snum,
3493 NT_PRINTER_INFO_LEVEL *printer = NULL;
3494 struct regval_ctr *ctr;
3495 struct regval_blob *guid_val;
3501 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3503 if (!W_ERROR_IS_OK(win_rc) ||
3504 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3505 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3506 !(ctr = printer->info_2->data->keys[i].values) ||
3507 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3509 free_a_printer(&printer, 2);
3513 /* fetching printer guids really ought to be a separate function. */
3518 /* We used to store the guid as REG_BINARY, then swapped
3519 to REG_SZ for Vista compatibility so check for both */
3521 switch ( regval_type(guid_val) ){
3523 blob = data_blob_const(regval_data_p(guid_val),
3524 regval_size(guid_val));
3525 pull_reg_sz(talloc_tos(), &blob, (const char **)&guid_str);
3526 ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3527 talloc_free(guid_str);
3530 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3534 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3537 DEBUG(0,("is_printer_published: GUID value stored as "
3538 "invaluid type (%d)\n", regval_type(guid_val) ));
3543 free_a_printer(&printer, 2);
3547 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3552 WERROR check_published_printers(void)
3557 bool is_printer_published(Printer_entry *print_hnd, int snum,
3562 #endif /* HAVE_ADS */
3564 /****************************************************************************
3565 ***************************************************************************/
3567 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3569 NT_PRINTER_DATA *data;
3571 int removed_keys = 0;
3575 empty_slot = data->num_keys;
3578 return WERR_INVALID_PARAM;
3580 /* remove all keys */
3582 if ( !strlen(key) ) {
3584 TALLOC_FREE( data );
3588 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3594 /* remove a specific key (and all subkeys) */
3596 for ( i=0; i<data->num_keys; i++ ) {
3597 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3598 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3599 data->keys[i].name));
3601 TALLOC_FREE( data->keys[i].name );
3602 TALLOC_FREE( data->keys[i].values );
3604 /* mark the slot as empty */
3606 ZERO_STRUCTP( &data->keys[i] );
3610 /* find the first empty slot */
3612 for ( i=0; i<data->num_keys; i++ ) {
3613 if ( !data->keys[i].name ) {
3620 if ( i == data->num_keys )
3621 /* nothing was removed */
3622 return WERR_INVALID_PARAM;
3624 /* move everything down */
3626 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3627 if ( data->keys[i].name ) {
3628 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3629 ZERO_STRUCTP( &data->keys[i] );
3637 data->num_keys -= removed_keys;
3639 /* sanity check to see if anything is left */
3641 if ( !data->num_keys ) {
3642 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3644 SAFE_FREE( data->keys );
3645 ZERO_STRUCTP( data );
3651 /****************************************************************************
3652 ***************************************************************************/
3654 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3656 WERROR result = WERR_OK;
3659 /* we must have names on non-zero length */
3661 if ( !key || !*key|| !value || !*value )
3662 return WERR_INVALID_NAME;
3664 /* find the printer key first */
3666 key_index = lookup_printerkey( p2->data, key );
3667 if ( key_index == -1 )
3670 /* make sure the value exists so we can return the correct error code */
3672 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3673 return WERR_BADFILE;
3675 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3677 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3683 /****************************************************************************
3684 ***************************************************************************/
3686 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3687 uint32 type, uint8 *data, int real_len )
3689 WERROR result = WERR_OK;
3692 /* we must have names on non-zero length */
3694 if ( !key || !*key|| !value || !*value )
3695 return WERR_INVALID_NAME;
3697 /* find the printer key first */
3699 key_index = lookup_printerkey( p2->data, key );
3700 if ( key_index == -1 )
3701 key_index = add_new_printer_key( p2->data, key );
3703 if ( key_index == -1 )
3706 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3707 type, data, real_len );
3709 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3710 key, value, type, real_len ));
3715 /****************************************************************************
3716 ***************************************************************************/
3718 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3722 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3725 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3728 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3731 /****************************************************************************
3732 Unpack a list of registry values frem the TDB
3733 ***************************************************************************/
3735 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3740 const char *valuename = NULL;
3741 const char *keyname = NULL;
3745 struct regval_blob *regval_p;
3748 /* add the "PrinterDriverData" key first for performance reasons */
3750 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3752 /* loop and unpack the rest of the registry values */
3756 /* check to see if there are any more registry values */
3759 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3763 /* unpack the next regval */
3765 len += tdb_unpack(buf+len, buflen-len, "fdB",
3771 /* lookup for subkey names which have a type of REG_NONE */
3772 /* there's no data with this entry */
3774 if ( type == REG_NONE ) {
3775 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3776 add_new_printer_key( printer_data, string );
3781 * break of the keyname from the value name.
3782 * Valuenames can have embedded '\'s so be careful.
3783 * only support one level of keys. See the
3784 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3788 str = strchr_m( string, '\\');
3790 /* Put in "PrinterDriverData" is no key specified */
3793 keyname = SPOOL_PRINTERDATA_KEY;
3802 /* see if we need a new key */
3804 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3805 key_index = add_new_printer_key( printer_data, keyname );
3807 if ( key_index == -1 ) {
3808 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3813 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3815 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3816 Thanks to Martin Zielinski for the hint. */
3818 if ( type == REG_BINARY &&
3819 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3820 strequal( valuename, "objectGUID" ) )
3824 /* convert the GUID to a UNICODE string */
3826 memcpy( &guid, data_p, sizeof(struct GUID) );
3828 regval_ctr_addvalue_sz(printer_data->keys[key_index].values,
3830 GUID_string(talloc_tos(), &guid));
3835 regval_ctr_addvalue( printer_data->keys[key_index].values,
3836 valuename, type, data_p,
3840 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3847 /****************************************************************************
3848 ***************************************************************************/
3850 static char *win_driver;
3851 static char *os2_driver;
3853 static const char *get_win_driver(void)
3855 if (win_driver == NULL) {
3861 static const char *get_os2_driver(void)
3863 if (os2_driver == NULL) {
3869 static bool set_driver_mapping(const char *from, const char *to)
3871 SAFE_FREE(win_driver);
3872 SAFE_FREE(os2_driver);
3874 win_driver = SMB_STRDUP(from);
3875 os2_driver = SMB_STRDUP(to);
3877 if (win_driver == NULL || os2_driver == NULL) {
3878 SAFE_FREE(win_driver);
3879 SAFE_FREE(os2_driver);
3885 static void map_to_os2_driver(fstring drivername)
3887 char *mapfile = lp_os2_driver_map();
3888 char **lines = NULL;
3892 if (!strlen(drivername))
3898 if (strequal(drivername, get_win_driver())) {
3899 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3900 drivername, get_os2_driver()));
3901 fstrcpy(drivername, get_os2_driver());
3905 lines = file_lines_load(mapfile, &numlines,0,NULL);
3906 if (numlines == 0 || lines == NULL) {
3907 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3912 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3914 for( i = 0; i < numlines; i++) {
3915 char *nt_name = lines[i];
3916 char *os2_name = strchr(nt_name,'=');
3923 while (isspace(*nt_name))
3926 if (!*nt_name || strchr("#;",*nt_name))
3930 int l = strlen(nt_name);
3931 while (l && isspace(nt_name[l-1])) {
3937 while (isspace(*os2_name))
3941 int l = strlen(os2_name);
3942 while (l && isspace(os2_name[l-1])) {
3948 if (strequal(nt_name,drivername)) {
3949 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3950 set_driver_mapping(drivername,os2_name);
3951 fstrcpy(drivername,os2_name);
3963 * @brief Map a Windows driver to a OS/2 driver.
3965 * @param[in] mem_ctx The memory context to use.
3967 * @param[in,out] pdrivername The drivername of Windows to remap.
3969 * @return WERR_OK on success, a corresponding WERROR on failure.
3971 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
3973 const char *mapfile = lp_os2_driver_map();
3974 char **lines = NULL;
3975 const char *drivername;
3979 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
3980 return WERR_INVALID_PARAMETER;
3983 drivername = *pdrivername;
3985 if (mapfile[0] == '\0') {
3986 return WERR_BADFILE;
3989 if (strequal(drivername, get_win_driver())) {
3990 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3991 drivername, get_os2_driver()));
3992 drivername = talloc_strdup(mem_ctx, get_os2_driver());
3993 if (drivername == NULL) {
3996 *pdrivername = drivername;
4000 lines = file_lines_load(mapfile, &numlines, 0, NULL);
4001 if (numlines == 0 || lines == NULL) {
4002 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
4007 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
4009 for( i = 0; i < numlines; i++) {
4010 char *nt_name = lines[i];
4011 char *os2_name = strchr(nt_name, '=');
4013 if (os2_name == NULL) {
4019 while (isspace(*nt_name)) {
4023 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
4028 int l = strlen(nt_name);
4029 while (l && isspace(nt_name[l - 1])) {
4035 while (isspace(*os2_name)) {
4040 int l = strlen(os2_name);
4041 while (l && isspace(os2_name[l-1])) {
4047 if (strequal(nt_name, drivername)) {
4048 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
4049 set_driver_mapping(drivername, os2_name);
4050 drivername = talloc_strdup(mem_ctx, os2_name);
4052 if (drivername == NULL) {
4055 *pdrivername = drivername;
4064 /****************************************************************************
4065 Get a default printer info 2 struct.
4066 ****************************************************************************/
4068 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
4069 const char *servername,
4070 const char* sharename,
4073 int snum = lp_servicenumber(sharename);
4075 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4076 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4077 servername, sharename);
4078 fstrcpy(info->sharename, sharename);
4079 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
4081 /* by setting the driver name to an empty string, a local NT admin
4082 can now run the **local** APW to install a local printer driver
4083 for a Samba shared printer in 2.2. Without this, drivers **must** be
4084 installed on the Samba server for NT clients --jerry */
4085 #if 0 /* JERRY --do not uncomment-- */
4086 if (!*info->drivername)
4087 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
4091 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
4093 strlcpy(info->comment, "", sizeof(info->comment));
4094 fstrcpy(info->printprocessor, "winprint");
4095 fstrcpy(info->datatype, "RAW");
4098 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4099 /* Pull the location and comment strings from cups if we don't
4101 if ( !strlen(info->location) || !strlen(info->comment) ) {
4102 char *comment = NULL;
4103 char *location = NULL;
4104 if (cups_pull_comment_location(info, info->sharename,
4105 &comment, &location)) {
4106 strlcpy(info->comment, comment, sizeof(info->comment));
4107 fstrcpy(info->location, location);
4108 TALLOC_FREE(comment);
4109 TALLOC_FREE(location);
4115 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
4117 info->starttime = 0; /* Minutes since 12:00am GMT */
4118 info->untiltime = 0; /* Minutes since 12:00am GMT */
4120 info->default_priority = 1;
4121 info->setuptime = (uint32)time(NULL);
4124 * I changed this as I think it is better to have a generic
4125 * DEVMODE than to crash Win2k explorer.exe --jerry
4126 * See the HP Deskjet 990c Win2k drivers for an example.
4128 * However the default devmode appears to cause problems
4129 * with the HP CLJ 8500 PCL driver. Hence the addition of
4130 * the "default devmode" parameter --jerry 22/01/2002
4133 if (lp_default_devmode(snum)) {
4134 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
4138 info->devmode = NULL;
4141 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4145 info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
4150 add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
4156 free_nt_devicemode(&info->devmode);
4158 return WERR_ACCESS_DENIED;
4161 /****************************************************************************
4162 ****************************************************************************/
4164 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
4165 const char *servername,
4166 const char *sharename,
4170 int snum = lp_servicenumber(sharename);
4171 TDB_DATA kbuf, dbuf;
4172 fstring printername;
4173 char adevice[MAXDEVICENAME];
4174 char *comment = NULL;
4176 kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4178 dbuf = tdb_fetch(tdb_printers, kbuf);
4180 return get_a_printer_2_default(info, servername,
4181 sharename, get_loc_com);
4184 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4187 &info->default_priority,
4194 &info->c_setprinter,
4204 info->printprocessor,
4209 strlcpy(info->comment, comment, sizeof(info->comment));
4213 /* Samba has to have shared raw drivers. */
4214 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4215 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4217 /* Restore the stripped strings. */
4218 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4220 if ( lp_force_printername(snum) ) {
4221 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4223 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4226 fstrcpy(info->printername, printername);
4229 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4230 /* Pull the location and comment strings from cups if we don't
4232 if ( !strlen(info->location) || !strlen(info->comment) ) {
4233 char *location = NULL;
4235 if (cups_pull_comment_location(info, info->sharename,
4236 &comment, &location)) {
4237 strlcpy(info->comment, comment, sizeof(info->comment));
4238 fstrcpy(info->location, location);
4239 TALLOC_FREE(comment);
4240 TALLOC_FREE(location);
4246 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4249 * Some client drivers freak out if there is a NULL devmode
4250 * (probably the driver is not checking before accessing
4251 * the devmode pointer) --jerry
4253 * See comments in get_a_printer_2_default()
4256 if (lp_default_devmode(snum) && !info->devmode) {
4257 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4259 info->devmode = construct_nt_devicemode(printername);
4262 slprintf( adevice, sizeof(adevice), "%s", info->printername );
4263 if (info->devmode) {
4264 fstrcpy(info->devmode->devicename, adevice);
4267 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4268 DEBUG(0,("unpack_values: talloc() failed!\n"));
4269 SAFE_FREE(dbuf.dptr);
4272 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4274 /* This will get the current RPC talloc context, but we should be
4275 passing this as a parameter... fixme... JRA ! */
4277 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4278 SAFE_FREE(dbuf.dptr);
4282 /* Fix for OS/2 drivers. */
4284 if (get_remote_arch() == RA_OS2) {
4285 map_to_os2_driver(info->drivername);
4288 SAFE_FREE(dbuf.dptr);
4290 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4291 sharename, info->printername, info->drivername));
4296 /****************************************************************************
4297 Debugging function, dump at level 6 the struct in the logs.
4298 ****************************************************************************/
4299 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4302 NT_PRINTER_INFO_LEVEL_2 *info2;
4304 DEBUG(106,("Dumping printer at level [%d]\n", level));
4309 if (printer->info_2 == NULL)
4313 info2=printer->info_2;
4315 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4316 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4317 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4318 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4319 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4320 DEBUGADD(106,("status:[%d]\n", info2->status));
4321 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4322 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4323 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4324 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4325 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4327 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4328 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4329 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4330 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4331 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4332 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4333 DEBUGADD(106,("location:[%s]\n", info2->location));
4334 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4335 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4336 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4337 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4343 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4351 /****************************************************************************
4352 Update the changeid time.
4353 This is SO NASTY as some drivers need this to change, others need it
4354 static. This value will change every second, and I must hope that this
4355 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4357 ****************************************************************************/
4359 static uint32 rev_changeid(void)
4363 get_process_uptime(&tv);
4366 /* Return changeid as msec since spooler restart */
4367 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4370 * This setting seems to work well but is too untested
4371 * to replace the above calculation. Left in for experiementation
4372 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4374 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4380 * The function below are the high level ones.
4381 * only those ones must be called from the spoolss code.
4385 /****************************************************************************
4386 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4387 ****************************************************************************/
4389 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4393 dump_a_printer(printer, level);
4399 * Update the changestamp. Emperical tests show that the
4400 * ChangeID is always updated,but c_setprinter is
4401 * global spooler variable (not per printer).
4404 /* ChangeID **must** be increasing over the lifetime
4405 of client's spoolss service in order for the
4406 client's cache to show updates */
4408 printer->info_2->changeid = rev_changeid();
4411 * Because one day someone will ask:
4412 * NT->NT An admin connection to a remote
4413 * printer show changes imeediately in
4414 * the properities dialog
4416 * A non-admin connection will only show the
4417 * changes after viewing the properites page
4418 * 2 times. Seems to be related to a
4419 * race condition in the client between the spooler
4420 * updating the local cache and the Explorer.exe GUI
4421 * actually displaying the properties.
4423 * This is fixed in Win2k. admin/non-admin
4424 * connections both display changes immediately.
4429 result=update_a_printer_2(printer->info_2);
4433 result=WERR_UNKNOWN_LEVEL;
4440 /****************************************************************************
4441 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4443 Previously the code had a memory allocation problem because it always
4444 used the TALLOC_CTX from the Printer_entry*. This context lasts
4445 as a long as the original handle is open. So if the client made a lot
4446 of getprinter[data]() calls, the memory usage would climb. Now we use
4447 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4448 still use the Printer_entry->ctx for maintaining the cache copy though
4449 since that object must live as long as the handle by definition.
4452 ****************************************************************************/
4454 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4455 const char *sharename, bool get_loc_com)
4460 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4462 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4463 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4469 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4470 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4471 TALLOC_FREE( *pp_printer );
4476 fstrcpy( servername, print_hnd->servername );
4478 fstrcpy( servername, "%L" );
4479 standard_sub_basic( "", "", servername,
4480 sizeof(servername)-1 );
4483 result = get_a_printer_2( (*pp_printer)->info_2,
4484 servername, sharename, get_loc_com);
4486 /* we have a new printer now. Save it with this handle */
4488 if ( !W_ERROR_IS_OK(result) ) {
4489 TALLOC_FREE( *pp_printer );
4490 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4491 sharename, (unsigned int)level, win_errstr(result)));
4495 dump_a_printer( *pp_printer, level);
4500 TALLOC_FREE( *pp_printer );
4501 return WERR_UNKNOWN_LEVEL;
4507 WERROR get_a_printer( Printer_entry *print_hnd,
4508 NT_PRINTER_INFO_LEVEL **pp_printer,
4510 const char *sharename)
4512 return get_a_printer_internal(print_hnd, pp_printer, level,
4516 WERROR get_a_printer_search( Printer_entry *print_hnd,
4517 NT_PRINTER_INFO_LEVEL **pp_printer,
4519 const char *sharename)
4521 return get_a_printer_internal(print_hnd, pp_printer, level,
4525 /****************************************************************************
4526 Deletes a NT_PRINTER_INFO_LEVEL struct.
4527 ****************************************************************************/
4529 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4531 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4538 if ( printer->info_2 )
4539 free_nt_printer_info_level_2(&printer->info_2);
4543 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4547 TALLOC_FREE(*pp_printer);
4552 /****************************************************************************
4553 ****************************************************************************/
4555 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
4556 struct spoolss_DriverInfo8 *_info8)
4558 struct spoolss_DriverInfo8 info8;
4564 info8.version = r->info.info3->version;
4565 info8.driver_name = r->info.info3->driver_name;
4566 info8.architecture = r->info.info3->architecture;
4567 info8.driver_path = r->info.info3->driver_path;
4568 info8.data_file = r->info.info3->data_file;
4569 info8.config_file = r->info.info3->config_file;
4570 info8.help_file = r->info.info3->help_file;
4571 info8.monitor_name = r->info.info3->monitor_name;
4572 info8.default_datatype = r->info.info3->default_datatype;
4573 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
4574 info8.dependent_files = r->info.info3->dependent_files->string;
4578 info8.version = r->info.info6->version;
4579 info8.driver_name = r->info.info6->driver_name;
4580 info8.architecture = r->info.info6->architecture;
4581 info8.driver_path = r->info.info6->driver_path;
4582 info8.data_file = r->info.info6->data_file;
4583 info8.config_file = r->info.info6->config_file;
4584 info8.help_file = r->info.info6->help_file;
4585 info8.monitor_name = r->info.info6->monitor_name;
4586 info8.default_datatype = r->info.info6->default_datatype;
4587 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
4588 info8.dependent_files = r->info.info6->dependent_files->string;
4590 info8.driver_date = r->info.info6->driver_date;
4591 info8.driver_version = r->info.info6->driver_version;
4592 info8.manufacturer_name = r->info.info6->manufacturer_name;
4593 info8.manufacturer_url = r->info.info6->manufacturer_url;
4594 info8.hardware_id = r->info.info6->hardware_id;
4595 info8.provider = r->info.info6->provider;
4598 info8.version = r->info.info8->version;
4599 info8.driver_name = r->info.info8->driver_name;
4600 info8.architecture = r->info.info8->architecture;
4601 info8.driver_path = r->info.info8->driver_path;
4602 info8.data_file = r->info.info8->data_file;
4603 info8.config_file = r->info.info8->config_file;
4604 info8.help_file = r->info.info8->help_file;
4605 info8.monitor_name = r->info.info8->monitor_name;
4606 info8.default_datatype = r->info.info8->default_datatype;
4607 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
4608 info8.dependent_files = r->info.info8->dependent_files->string;
4610 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
4611 info8.previous_names = r->info.info8->previous_names->string;
4613 info8.driver_date = r->info.info8->driver_date;
4614 info8.driver_version = r->info.info8->driver_version;
4615 info8.manufacturer_name = r->info.info8->manufacturer_name;
4616 info8.manufacturer_url = r->info.info8->manufacturer_url;
4617 info8.hardware_id = r->info.info8->hardware_id;
4618 info8.provider = r->info.info8->provider;
4619 info8.print_processor = r->info.info8->print_processor;
4620 info8.vendor_setup = r->info.info8->vendor_setup;
4621 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
4622 info8.color_profiles = r->info.info8->color_profiles->string;
4624 info8.inf_path = r->info.info8->inf_path;
4625 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
4626 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
4627 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
4629 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
4630 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
4642 uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx,
4643 struct spoolss_AddDriverInfoCtr *r,
4647 struct spoolss_DriverInfo8 info8;
4651 DEBUG(10,("adding a printer at level [%d]\n", r->level));
4653 if (!driver_info_ctr_to_info8(r, &info8)) {
4657 *driver_name = talloc_strdup(mem_ctx, info8.driver_name);
4658 if (!*driver_name) {
4661 *version = info8.version;
4663 return add_a_printer_driver_8(&info8);
4666 /****************************************************************************
4667 ****************************************************************************/
4669 WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx,
4670 struct spoolss_DriverInfo8 **driver,
4671 const char *drivername, const char *architecture,
4675 struct spoolss_DriverInfo3 info3;
4676 struct spoolss_DriverInfo8 *info8;
4680 /* Sometime we just want any version of the driver */
4682 if (version == DRIVER_ANY_VERSION) {
4683 /* look for Win2k first and then for NT4 */
4684 result = get_a_printer_driver_3(mem_ctx,
4688 if (!W_ERROR_IS_OK(result)) {
4689 result = get_a_printer_driver_3(mem_ctx,
4695 result = get_a_printer_driver_3(mem_ctx,
4702 if (!W_ERROR_IS_OK(result)) {
4706 info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8);
4711 info8->version = info3.version;
4712 info8->driver_name = info3.driver_name;
4713 info8->architecture = info3.architecture;
4714 info8->driver_path = info3.driver_path;
4715 info8->data_file = info3.data_file;
4716 info8->config_file = info3.config_file;
4717 info8->help_file = info3.help_file;
4718 info8->dependent_files = info3.dependent_files;
4719 info8->monitor_name = info3.monitor_name;
4720 info8->default_datatype = info3.default_datatype;
4727 /****************************************************************************
4728 ****************************************************************************/
4730 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver)
4732 talloc_free(driver);
4737 /****************************************************************************
4738 Determine whether or not a particular driver is currently assigned
4740 ****************************************************************************/
4742 bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r)
4745 int n_services = lp_numservices();
4746 NT_PRINTER_INFO_LEVEL *printer = NULL;
4747 bool in_use = False;
4753 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4755 /* loop through the printers.tdb and check for the drivername */
4757 for (snum=0; snum<n_services && !in_use; snum++) {
4758 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4761 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4764 if (strequal(r->driver_name, printer->info_2->drivername))
4767 free_a_printer( &printer, 2 );
4770 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4773 struct spoolss_DriverInfo8 *d;
4776 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
4778 /* we can still remove the driver if there is one of
4779 "Windows NT x86" version 2 or 3 left */
4781 if (!strequal("Windows NT x86", r->architecture)) {
4782 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION);
4785 switch (r->version) {
4787 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3);
4790 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2);
4793 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4795 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4800 /* now check the error code */
4802 if ( W_ERROR_IS_OK(werr) ) {
4803 /* it's ok to remove the driver, we have other architctures left */
4805 free_a_printer_driver(d);
4809 /* report that the driver is not in use by default */
4815 /**********************************************************************
4816 Check to see if a ogiven file is in use by *info
4817 *********************************************************************/
4819 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
4826 /* mz: skip files that are in the list but already deleted */
4827 if (!file || !file[0]) {
4831 if (strequal(file, info->driver_path))
4834 if (strequal(file, info->data_file))
4837 if (strequal(file, info->config_file))
4840 if (strequal(file, info->help_file))
4843 /* see of there are any dependent files to examine */
4845 if (!info->dependent_files)
4848 while (info->dependent_files[i] && *info->dependent_files[i]) {
4849 if (strequal(file, info->dependent_files[i]))
4858 /**********************************************************************
4859 Utility function to remove the dependent file pointed to by the
4860 input parameter from the list
4861 *********************************************************************/
4863 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
4866 /* bump everything down a slot */
4868 while (files && files[idx+1]) {
4869 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
4878 /**********************************************************************
4879 Check if any of the files used by src are also used by drv
4880 *********************************************************************/
4882 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
4883 struct spoolss_DriverInfo8 *src,
4884 const struct spoolss_DriverInfo8 *drv)
4886 bool in_use = False;
4892 /* check each file. Remove it from the src structure if it overlaps */
4894 if (drv_file_in_use(src->driver_path, drv)) {
4896 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
4897 src->driver_path = talloc_strdup(mem_ctx, "");
4898 if (!src->driver_path) { return false; }
4901 if (drv_file_in_use(src->data_file, drv)) {
4903 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
4904 src->data_file = talloc_strdup(mem_ctx, "");
4905 if (!src->data_file) { return false; }
4908 if (drv_file_in_use(src->config_file, drv)) {
4910 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
4911 src->config_file = talloc_strdup(mem_ctx, "");
4912 if (!src->config_file) { return false; }
4915 if (drv_file_in_use(src->help_file, drv)) {
4917 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
4918 src->help_file = talloc_strdup(mem_ctx, "");
4919 if (!src->help_file) { return false; }
4922 /* are there any dependentfiles to examine? */
4924 if (!src->dependent_files)
4927 while (src->dependent_files[i] && *src->dependent_files[i]) {
4928 if (drv_file_in_use(src->dependent_files[i], drv)) {
4930 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
4931 trim_dependent_file(mem_ctx, src->dependent_files, i);
4939 /****************************************************************************
4940 Determine whether or not a particular driver files are currently being
4941 used by any other driver.
4943 Return value is True if any files were in use by other drivers
4944 and False otherwise.
4946 Upon return, *info has been modified to only contain the driver files
4947 which are not in use
4951 This needs to check all drivers to ensure that all files in use
4952 have been removed from *info, not just the ones in the first
4954 ****************************************************************************/
4956 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
4957 struct spoolss_DriverInfo8 *info)
4962 fstring *list = NULL;
4963 struct spoolss_DriverInfo8 *driver;
4964 bool in_use = false;
4969 version = info->version;
4971 /* loop over all driver versions */
4973 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4975 /* get the list of drivers */
4978 ndrivers = get_ntdrivers(&list, info->architecture, version);
4980 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4981 ndrivers, info->architecture, version));
4983 /* check each driver for overlap in files */
4985 for (i=0; i<ndrivers; i++) {
4986 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4990 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, list[i], info->architecture, version))) {
4995 /* check if d2 uses any files from d1 */
4996 /* only if this is a different driver than the one being deleted */
4998 if (!strequal(info->driver_name, driver->driver_name)) {
4999 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
5000 /* mz: Do not instantly return -
5001 * we need to ensure this file isn't
5002 * also in use by other drivers. */
5007 free_a_printer_driver(driver);
5012 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5017 static NTSTATUS driver_unlink_internals(connection_struct *conn,
5020 struct smb_filename *smb_fname = NULL;
5023 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
5025 if (!NT_STATUS_IS_OK(status)) {
5029 status = unlink_internals(conn, NULL, 0, smb_fname, false);
5031 TALLOC_FREE(smb_fname);
5035 /****************************************************************************
5036 Actually delete the driver files. Make sure that
5037 printer_driver_files_in_use() return False before calling
5039 ****************************************************************************/
5041 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
5042 const struct spoolss_DriverInfo8 *r)
5047 connection_struct *conn;
5050 fstring printdollar;
5051 int printdollar_snum;
5058 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
5059 r->driver_name, r->version));
5061 fstrcpy(printdollar, "print$");
5063 printdollar_snum = find_service(printdollar);
5064 if (printdollar_snum == -1) {
5068 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5069 lp_pathname(printdollar_snum),
5070 rpc_pipe->server_info, &oldcwd);
5071 if (!NT_STATUS_IS_OK(nt_status)) {
5072 DEBUG(0,("delete_driver_files: create_conn_struct "
5073 "returned %s\n", nt_errstr(nt_status)));
5077 if ( !CAN_WRITE(conn) ) {
5078 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5082 /* now delete the files; must strip the '\print$' string from
5085 if (r->driver_path && r->driver_path[0]) {
5086 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
5088 DEBUG(10,("deleting driverfile [%s]\n", s));
5089 driver_unlink_internals(conn, file);
5093 if (r->config_file && r->config_file[0]) {
5094 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
5096 DEBUG(10,("deleting configfile [%s]\n", s));
5097 driver_unlink_internals(conn, file);
5101 if (r->data_file && r->data_file[0]) {
5102 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
5104 DEBUG(10,("deleting datafile [%s]\n", s));
5105 driver_unlink_internals(conn, file);
5109 if (r->help_file && r->help_file[0]) {
5110 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
5112 DEBUG(10,("deleting helpfile [%s]\n", s));
5113 driver_unlink_internals(conn, file);
5117 /* check if we are done removing files */
5119 if (r->dependent_files) {
5120 while (r->dependent_files[i] && r->dependent_files[i][0]) {
5123 /* bypass the "\print$" portion of the path */
5125 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
5127 DEBUG(10,("deleting dependent file [%s]\n", file));
5128 driver_unlink_internals(conn, file);
5140 vfs_ChDir(conn, oldcwd);
5146 /****************************************************************************
5147 Remove a printer driver from the TDB. This assumes that the the driver was
5148 previously looked up.
5149 ***************************************************************************/
5151 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5152 const struct spoolss_DriverInfo8 *r,
5153 uint32 version, bool delete_files )
5159 /* delete the tdb data first */
5161 arch = get_short_archi(r->architecture);
5163 return WERR_UNKNOWN_PRINTER_DRIVER;
5165 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5166 arch, version, r->driver_name) < 0) {
5170 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5171 key, delete_files ? "TRUE" : "FALSE" ));
5173 /* check if the driver actually exists for this environment */
5175 dbuf = tdb_fetch_bystring( tdb_drivers, key );
5177 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5179 return WERR_UNKNOWN_PRINTER_DRIVER;
5182 SAFE_FREE( dbuf.dptr );
5184 /* ok... the driver exists so the delete should return success */
5186 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5187 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5189 return WERR_ACCESS_DENIED;
5193 * now delete any associated files if delete_files == True
5194 * even if this part failes, we return succes because the
5195 * driver doesn not exist any more
5199 delete_driver_files(rpc_pipe, r);
5201 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5207 /****************************************************************************
5208 Store a security desc for a printer.
5209 ****************************************************************************/
5211 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
5213 struct sec_desc_buf *new_secdesc_ctr = NULL;
5214 struct sec_desc_buf *old_secdesc_ctr = NULL;
5215 TALLOC_CTX *mem_ctx = NULL;
5222 mem_ctx = talloc_init("nt_printing_setsec");
5223 if (mem_ctx == NULL)
5226 /* The old owner and group sids of the security descriptor are not
5227 present when new ACEs are added or removed by changing printer
5228 permissions through NT. If they are NULL in the new security
5229 descriptor then copy them over from the old one. */
5231 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5232 struct dom_sid *owner_sid, *group_sid;
5233 struct security_acl *dacl, *sacl;
5234 struct security_descriptor *psd = NULL;
5237 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5238 status = WERR_NOMEM;
5242 /* Pick out correct owner and group sids */
5244 owner_sid = secdesc_ctr->sd->owner_sid ?
5245 secdesc_ctr->sd->owner_sid :
5246 old_secdesc_ctr->sd->owner_sid;
5248 group_sid = secdesc_ctr->sd->group_sid ?
5249 secdesc_ctr->sd->group_sid :
5250 old_secdesc_ctr->sd->group_sid;
5252 dacl = secdesc_ctr->sd->dacl ?
5253 secdesc_ctr->sd->dacl :
5254 old_secdesc_ctr->sd->dacl;
5256 sacl = secdesc_ctr->sd->sacl ?
5257 secdesc_ctr->sd->sacl :
5258 old_secdesc_ctr->sd->sacl;
5260 /* Make a deep copy of the security descriptor */
5262 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5263 owner_sid, group_sid,
5269 status = WERR_NOMEM;
5273 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5276 if (!new_secdesc_ctr) {
5277 new_secdesc_ctr = secdesc_ctr;
5280 /* Store the security descriptor in a tdb */
5282 nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5283 &blob.data, &blob.length);
5284 if (!NT_STATUS_IS_OK(nt_status)) {
5285 status = ntstatus_to_werror(nt_status);
5289 kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5291 dbuf.dptr = (unsigned char *)blob.data;
5292 dbuf.dsize = blob.length;
5294 if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5297 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5298 status = WERR_BADFUNC;
5301 /* Free malloc'ed memory */
5302 talloc_free(blob.data);
5307 talloc_destroy(mem_ctx);
5311 /****************************************************************************
5312 Construct a default security descriptor buffer for a printer.
5313 ****************************************************************************/
5315 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
5317 struct security_ace ace[5]; /* max number of ace entries */
5320 struct security_acl *psa = NULL;
5321 struct sec_desc_buf *sdb = NULL;
5322 struct security_descriptor *psd = NULL;
5323 struct dom_sid adm_sid;
5326 /* Create an ACE where Everyone is allowed to print */
5328 sa = PRINTER_ACE_PRINT;
5329 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5330 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5332 /* Add the domain admins group if we are a DC */
5335 struct dom_sid domadmins_sid;
5337 sid_compose(&domadmins_sid, get_global_sam_sid(),
5340 sa = PRINTER_ACE_FULL_CONTROL;
5341 init_sec_ace(&ace[i++], &domadmins_sid,
5342 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5343 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5344 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5345 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5347 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5348 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
5350 sa = PRINTER_ACE_FULL_CONTROL;
5351 init_sec_ace(&ace[i++], &adm_sid,
5352 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5353 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5354 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5355 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5358 /* add BUILTIN\Administrators as FULL CONTROL */
5360 sa = PRINTER_ACE_FULL_CONTROL;
5361 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5362 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5363 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5364 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5365 SEC_ACE_TYPE_ACCESS_ALLOWED,
5366 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5368 /* Make the security descriptor owned by the BUILTIN\Administrators */
5370 /* The ACL revision number in rpc_secdesc.h differs from the one
5371 created by NT when setting ACE entries in printer
5372 descriptors. NT4 complains about the property being edited by a
5375 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5376 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
5377 &global_sid_Builtin_Administrators,
5378 &global_sid_Builtin_Administrators,
5379 NULL, psa, &sd_size);
5383 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5387 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5389 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5390 (unsigned int)sd_size));
5395 /****************************************************************************
5396 Get a security desc for a printer.
5397 ****************************************************************************/
5399 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
5407 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5408 sharename = temp + 1;
5411 /* Fetch security descriptor from tdb */
5413 kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5415 dbuf = tdb_fetch(tdb_printers, kbuf);
5418 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5420 SAFE_FREE(dbuf.dptr);
5422 if (NT_STATUS_IS_OK(status)) {
5427 *secdesc_ctr = construct_default_printer_sdb(ctx);
5428 if (!*secdesc_ctr) {
5432 status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5433 &blob.data, &blob.length);
5434 if (NT_STATUS_IS_OK(status)) {
5435 dbuf.dptr = (unsigned char *)blob.data;
5436 dbuf.dsize = blob.length;
5437 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5438 talloc_free(blob.data);
5441 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5442 this security descriptor has been created when winbindd was
5443 down. Take ownership of security descriptor. */
5445 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5446 struct dom_sid owner_sid;
5448 /* Change sd owner to workgroup administrator */
5450 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5451 struct sec_desc_buf *new_secdesc_ctr = NULL;
5452 struct security_descriptor *psd = NULL;
5457 sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
5459 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5461 (*secdesc_ctr)->sd->group_sid,
5462 (*secdesc_ctr)->sd->sacl,
5463 (*secdesc_ctr)->sd->dacl,
5470 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5471 if (!new_secdesc_ctr) {
5475 /* Swap with other one */
5477 *secdesc_ctr = new_secdesc_ctr;
5481 nt_printing_setsec(sharename, *secdesc_ctr);
5485 if (DEBUGLEVEL >= 10) {
5486 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
5489 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5490 sharename, the_acl->num_aces));
5492 for (i = 0; i < the_acl->num_aces; i++) {
5493 DEBUG(10, ("%s %d %d 0x%08x\n",
5494 sid_string_dbg(&the_acl->aces[i].trustee),
5495 the_acl->aces[i].type, the_acl->aces[i].flags,
5496 the_acl->aces[i].access_mask));
5505 1: level not implemented
5506 2: file doesn't exist
5507 3: can't allocate memory
5508 4: can't free memory
5509 5: non existant struct
5513 A printer and a printer driver are 2 different things.
5514 NT manages them separatelly, Samba does the same.
5515 Why ? Simply because it's easier and it makes sense !
5517 Now explanation: You have 3 printers behind your samba server,
5518 2 of them are the same make and model (laser A and B). But laser B
5519 has an 3000 sheet feeder and laser A doesn't such an option.
5520 Your third printer is an old dot-matrix model for the accounting :-).
5522 If the /usr/local/samba/lib directory (default dir), you will have
5523 5 files to describe all of this.
5525 3 files for the printers (1 by printer):
5528 NTprinter_accounting
5529 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5530 NTdriver_printer model X
5531 NTdriver_printer model Y
5533 jfm: I should use this comment for the text file to explain
5534 same thing for the forms BTW.
5535 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5539 /* Convert generic access rights to printer object specific access rights.
5540 It turns out that NT4 security descriptors use generic access rights and
5541 NT5 the object specific ones. */
5543 void map_printer_permissions(struct security_descriptor *sd)
5547 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5548 se_map_generic(&sd->dacl->aces[i].access_mask,
5549 &printer_generic_mapping);
5553 void map_job_permissions(struct security_descriptor *sd)
5557 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5558 se_map_generic(&sd->dacl->aces[i].access_mask,
5559 &job_generic_mapping);
5564 /****************************************************************************
5565 Check a user has permissions to perform the given operation. We use the
5566 permission constants defined in include/rpc_spoolss.h to check the various
5567 actions we perform when checking printer access.
5569 PRINTER_ACCESS_ADMINISTER:
5570 print_queue_pause, print_queue_resume, update_printer_sec,
5571 update_printer, spoolss_addprinterex_level_2,
5572 _spoolss_setprinterdata
5577 JOB_ACCESS_ADMINISTER:
5578 print_job_delete, print_job_pause, print_job_resume,
5581 Try access control in the following order (for performance reasons):
5582 1) root and SE_PRINT_OPERATOR can do anything (easy check)
5583 2) check security descriptor (bit comparisons in memory)
5584 3) "printer admins" (may result in numerous calls to winbind)
5586 ****************************************************************************/
5587 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5590 struct sec_desc_buf *secdesc = NULL;
5591 uint32 access_granted;
5594 TALLOC_CTX *mem_ctx = NULL;
5595 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5597 /* If user is NULL then use the current_user structure */
5599 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5601 if (server_info->utok.uid == sec_initial_uid()
5602 || user_has_privileges(server_info->ptok, &se_printop ) ) {
5606 /* Get printer name */
5608 pname = PRINTERNAME(snum);
5610 if (!pname || !*pname) {
5615 /* Get printer security descriptor */
5617 if(!(mem_ctx = talloc_init("print_access_check"))) {
5622 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5623 talloc_destroy(mem_ctx);
5628 if (access_type == JOB_ACCESS_ADMINISTER) {
5629 struct sec_desc_buf *parent_secdesc = secdesc;
5631 /* Create a child security descriptor to check permissions
5632 against. This is because print jobs are child objects
5633 objects of a printer. */
5635 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5637 if (!NT_STATUS_IS_OK(status)) {
5638 talloc_destroy(mem_ctx);
5639 errno = map_errno_from_nt_status(status);
5643 map_job_permissions(secdesc->sd);
5645 map_printer_permissions(secdesc->sd);
5649 status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5652 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5654 /* see if we need to try the printer admin list */
5656 if (!NT_STATUS_IS_OK(status) &&
5657 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5658 NULL, NULL, server_info->ptok,
5659 lp_printer_admin(snum)))) {
5660 talloc_destroy(mem_ctx);
5664 talloc_destroy(mem_ctx);
5666 if (!NT_STATUS_IS_OK(status)) {
5670 return NT_STATUS_IS_OK(status);
5673 /****************************************************************************
5674 Check the time parameters allow a print operation.
5675 *****************************************************************************/
5677 bool print_time_access_check(const char *servicename)
5679 NT_PRINTER_INFO_LEVEL *printer = NULL;
5681 time_t now = time(NULL);
5685 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5688 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5692 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5694 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5697 free_a_printer(&printer, 2);
5705 /****************************************************************************
5706 Fill in the servername sent in the _spoolss_open_printer_ex() call
5707 ****************************************************************************/
5709 char* get_server_name( Printer_entry *printer )
5711 return printer->servername;