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 )
2901 if ( !name || !data )
2904 /* allocate another slot in the NT_PRINTER_KEY array */
2906 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2907 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2913 key_index = data->num_keys;
2915 /* initialze new key */
2917 data->keys[key_index].name = talloc_strdup( data, name );
2919 if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, struct regval_ctr )) )
2924 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2929 /****************************************************************************
2930 search for a registry key name in the existing printer data
2931 ***************************************************************************/
2933 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2937 for ( i=0; i<data->num_keys; i++ ) {
2938 if ( strequal( data->keys[i].name, name ) ) {
2940 /* cleanup memory */
2942 TALLOC_FREE( data->keys[i].name );
2943 TALLOC_FREE( data->keys[i].values );
2945 /* if not the end of the array, move remaining elements down one slot */
2948 if ( data->num_keys && (i < data->num_keys) )
2949 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2956 return data->num_keys;
2959 /****************************************************************************
2960 search for a registry key name in the existing printer data
2961 ***************************************************************************/
2963 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2968 if ( !data || !name )
2971 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2973 /* loop over all existing keys */
2975 for ( i=0; i<data->num_keys; i++ ) {
2976 if ( strequal(data->keys[i].name, name) ) {
2977 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2987 /****************************************************************************
2988 ***************************************************************************/
2990 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2994 int num_subkeys = 0;
2996 fstring *subkeys_ptr = NULL;
3007 /* special case of asking for the top level printer data registry key names */
3009 if ( strlen(key) == 0 ) {
3010 for ( i=0; i<data->num_keys; i++ ) {
3012 /* found a match, so allocate space and copy the name */
3014 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3015 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3020 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
3027 /* asking for the subkeys of some key */
3028 /* subkey paths are stored in the key name using '\' as the delimiter */
3030 for ( i=0; i<data->num_keys; i++ ) {
3031 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
3033 /* if we found the exact key, then break */
3034 key_len = strlen( key );
3035 if ( strlen(data->keys[i].name) == key_len )
3038 /* get subkey path */
3040 p = data->keys[i].name + key_len;
3043 fstrcpy( subkeyname, p );
3044 if ( (p = strchr( subkeyname, '\\' )) )
3047 /* don't add a key more than once */
3049 for ( j=0; j<num_subkeys; j++ ) {
3050 if ( strequal( subkeys_ptr[j], subkeyname ) )
3054 if ( j != num_subkeys )
3057 /* found a match, so allocate space and copy the name */
3059 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3060 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3065 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
3071 /* return error if the key was not found */
3073 if ( i == data->num_keys ) {
3074 SAFE_FREE(subkeys_ptr);
3079 /* tag off the end */
3082 fstrcpy(subkeys_ptr[num_subkeys], "" );
3084 *subkeys = subkeys_ptr;
3090 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3093 regval_ctr_delvalue(ctr, val_name);
3094 regval_ctr_addvalue_sz(ctr, val_name, sz);
3097 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
3100 regval_ctr_delvalue(ctr, val_name);
3101 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
3102 (char *) &dword, sizeof(dword));
3105 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
3108 uint8 bin_bool = (b ? 1 : 0);
3109 regval_ctr_delvalue(ctr, val_name);
3110 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
3111 (char *) &bin_bool, sizeof(bin_bool));
3114 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3115 const char *multi_sz)
3122 regval_ctr_delvalue(ctr, val_name);
3123 regval_ctr_addvalue_multi_sz(ctr, val_name, a);
3126 /****************************************************************************
3127 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3129 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3130 * @return bool indicating success or failure
3131 ***************************************************************************/
3133 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
3135 struct regval_ctr *ctr = NULL;
3137 const char *dnssuffix;
3138 char *allocated_string = NULL;
3139 const char *ascii_str;
3142 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3143 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3144 ctr = info2->data->keys[i].values;
3146 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3147 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3149 /* we make the assumption that the netbios name is the same
3150 as the DNS name sinc ethe former will be what we used to
3153 dnssuffix = get_mydnsdomname(talloc_tos());
3154 if (dnssuffix && *dnssuffix) {
3155 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3157 fstrcpy( longname, global_myname() );
3160 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3162 if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3165 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3166 SAFE_FREE(allocated_string);
3168 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3169 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3170 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3171 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3172 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3173 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3174 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3175 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3176 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3178 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3179 (info2->attributes &
3180 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3182 switch (info2->attributes & 0x3) {
3184 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3187 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3190 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3193 ascii_str = "unknown";
3195 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3200 /*****************************************************************
3201 ****************************************************************/
3203 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3207 struct regval_ctr *ctr=NULL;
3209 /* find the DsSpooler key */
3210 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3211 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3212 ctr = info2->data->keys[i].values;
3214 regval_ctr_delvalue(ctr, "objectGUID");
3216 /* We used to store this as a REG_BINARY but that causes
3219 regval_ctr_addvalue_sz(ctr, "objectGUID",
3220 GUID_string(talloc_tos(), &guid));
3223 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3224 NT_PRINTER_INFO_LEVEL *printer)
3228 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3229 char *srv_dn_utf8, **srv_cn_utf8;
3232 const char *attrs[] = {"objectGUID", NULL};
3234 WERROR win_rc = WERR_OK;
3235 size_t converted_size;
3237 /* build the ads mods */
3238 ctx = talloc_init("nt_printer_publish_ads");
3243 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3245 /* figure out where to publish */
3246 ads_find_machine_acct(ads, &res, global_myname());
3248 /* We use ldap_get_dn here as we need the answer
3249 * in utf8 to call ldap_explode_dn(). JRA. */
3251 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3254 return WERR_SERVER_UNAVAILABLE;
3256 ads_msgfree(ads, res);
3257 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3260 ldap_memfree(srv_dn_utf8);
3261 return WERR_SERVER_UNAVAILABLE;
3263 /* Now convert to CH_UNIX. */
3264 if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3266 ldap_memfree(srv_dn_utf8);
3267 ldap_memfree(srv_cn_utf8);
3268 return WERR_SERVER_UNAVAILABLE;
3270 if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3272 ldap_memfree(srv_dn_utf8);
3273 ldap_memfree(srv_cn_utf8);
3274 TALLOC_FREE(srv_dn);
3275 return WERR_SERVER_UNAVAILABLE;
3278 ldap_memfree(srv_dn_utf8);
3279 ldap_memfree(srv_cn_utf8);
3281 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3282 if (!srv_cn_escaped) {
3284 return WERR_SERVER_UNAVAILABLE;
3286 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3287 if (!sharename_escaped) {
3288 SAFE_FREE(srv_cn_escaped);
3290 return WERR_SERVER_UNAVAILABLE;
3293 prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3295 SAFE_FREE(srv_cn_escaped);
3296 SAFE_FREE(sharename_escaped);
3298 mods = ads_init_mods(ctx);
3306 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3307 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3308 printer->info_2->sharename);
3311 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3312 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3314 for (i=0; mods[i] != 0; i++)
3316 mods[i] = (LDAPMod *)-1;
3317 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3320 if (!ADS_ERR_OK(ads_rc))
3321 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3323 /* retreive the guid and store it locally */
3324 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3326 ads_pull_guid(ads, res, &guid);
3327 ads_msgfree(ads, res);
3328 store_printer_guid(printer->info_2, guid);
3329 win_rc = mod_a_printer(printer, 2);
3336 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3337 NT_PRINTER_INFO_LEVEL *printer)
3340 LDAPMessage *res = NULL;
3341 char *prt_dn = NULL;
3343 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3345 /* remove the printer from the directory */
3346 ads_rc = ads_find_printer_on_server(ads, &res,
3347 printer->info_2->sharename, global_myname());
3349 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3350 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3352 ads_msgfree(ads, res);
3355 ads_rc = ads_del_dn(ads, prt_dn);
3356 TALLOC_FREE(prt_dn);
3360 ads_msgfree(ads, res);
3365 /****************************************************************************
3366 * Publish a printer in the directory
3368 * @param snum describing printer service
3369 * @return WERROR indicating status of publishing
3370 ***************************************************************************/
3372 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3375 ADS_STRUCT *ads = NULL;
3376 NT_PRINTER_INFO_LEVEL *printer = NULL;
3379 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3380 if (!W_ERROR_IS_OK(win_rc))
3384 case DSPRINT_PUBLISH:
3385 case DSPRINT_UPDATE:
3386 /* set the DsSpooler info and attributes */
3387 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3388 win_rc = WERR_NOMEM;
3392 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3394 case DSPRINT_UNPUBLISH:
3395 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3398 win_rc = WERR_NOT_SUPPORTED;
3402 win_rc = mod_a_printer(printer, 2);
3403 if (!W_ERROR_IS_OK(win_rc)) {
3404 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3408 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3410 DEBUG(3, ("ads_init() failed\n"));
3411 win_rc = WERR_SERVER_UNAVAILABLE;
3414 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3415 SAFE_FREE(ads->auth.password);
3416 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3419 /* ads_connect() will find the DC for us */
3420 ads_rc = ads_connect(ads);
3421 if (!ADS_ERR_OK(ads_rc)) {
3422 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3423 win_rc = WERR_ACCESS_DENIED;
3428 case DSPRINT_PUBLISH:
3429 case DSPRINT_UPDATE:
3430 win_rc = nt_printer_publish_ads(ads, printer);
3432 case DSPRINT_UNPUBLISH:
3433 win_rc = nt_printer_unpublish_ads(ads, printer);
3438 free_a_printer(&printer, 2);
3443 WERROR check_published_printers(void)
3446 ADS_STRUCT *ads = NULL;
3448 int n_services = lp_numservices();
3449 NT_PRINTER_INFO_LEVEL *printer = NULL;
3451 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3453 DEBUG(3, ("ads_init() failed\n"));
3454 return WERR_SERVER_UNAVAILABLE;
3456 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3457 SAFE_FREE(ads->auth.password);
3458 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3461 /* ads_connect() will find the DC for us */
3462 ads_rc = ads_connect(ads);
3463 if (!ADS_ERR_OK(ads_rc)) {
3464 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3466 ads_kdestroy("MEMORY:prtpub_cache");
3467 return WERR_ACCESS_DENIED;
3470 for (snum = 0; snum < n_services; snum++) {
3471 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3474 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3475 lp_servicename(snum))) &&
3476 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3477 nt_printer_publish_ads(ads, printer);
3479 free_a_printer(&printer, 2);
3483 ads_kdestroy("MEMORY:prtpub_cache");
3487 bool is_printer_published(Printer_entry *print_hnd, int snum,
3490 NT_PRINTER_INFO_LEVEL *printer = NULL;
3491 struct regval_ctr *ctr;
3492 struct regval_blob *guid_val;
3498 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3500 if (!W_ERROR_IS_OK(win_rc) ||
3501 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3502 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3503 !(ctr = printer->info_2->data->keys[i].values) ||
3504 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3506 free_a_printer(&printer, 2);
3510 /* fetching printer guids really ought to be a separate function. */
3515 /* We used to store the guid as REG_BINARY, then swapped
3516 to REG_SZ for Vista compatibility so check for both */
3518 switch ( regval_type(guid_val) ){
3520 blob = data_blob_const(regval_data_p(guid_val),
3521 regval_size(guid_val));
3522 pull_reg_sz(talloc_tos(), &blob, (const char **)&guid_str);
3523 ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3524 talloc_free(guid_str);
3527 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3531 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3534 DEBUG(0,("is_printer_published: GUID value stored as "
3535 "invaluid type (%d)\n", regval_type(guid_val) ));
3540 free_a_printer(&printer, 2);
3544 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3549 WERROR check_published_printers(void)
3554 bool is_printer_published(Printer_entry *print_hnd, int snum,
3559 #endif /* HAVE_ADS */
3561 /****************************************************************************
3562 ***************************************************************************/
3564 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3566 NT_PRINTER_DATA *data;
3568 int removed_keys = 0;
3572 empty_slot = data->num_keys;
3575 return WERR_INVALID_PARAM;
3577 /* remove all keys */
3579 if ( !strlen(key) ) {
3581 TALLOC_FREE( data );
3585 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3591 /* remove a specific key (and all subkeys) */
3593 for ( i=0; i<data->num_keys; i++ ) {
3594 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3595 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3596 data->keys[i].name));
3598 TALLOC_FREE( data->keys[i].name );
3599 TALLOC_FREE( data->keys[i].values );
3601 /* mark the slot as empty */
3603 ZERO_STRUCTP( &data->keys[i] );
3607 /* find the first empty slot */
3609 for ( i=0; i<data->num_keys; i++ ) {
3610 if ( !data->keys[i].name ) {
3617 if ( i == data->num_keys )
3618 /* nothing was removed */
3619 return WERR_INVALID_PARAM;
3621 /* move everything down */
3623 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3624 if ( data->keys[i].name ) {
3625 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3626 ZERO_STRUCTP( &data->keys[i] );
3634 data->num_keys -= removed_keys;
3636 /* sanity check to see if anything is left */
3638 if ( !data->num_keys ) {
3639 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3641 SAFE_FREE( data->keys );
3642 ZERO_STRUCTP( data );
3648 /****************************************************************************
3649 ***************************************************************************/
3651 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3653 WERROR result = WERR_OK;
3656 /* we must have names on non-zero length */
3658 if ( !key || !*key|| !value || !*value )
3659 return WERR_INVALID_NAME;
3661 /* find the printer key first */
3663 key_index = lookup_printerkey( p2->data, key );
3664 if ( key_index == -1 )
3667 /* make sure the value exists so we can return the correct error code */
3669 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3670 return WERR_BADFILE;
3672 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3674 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3680 /****************************************************************************
3681 ***************************************************************************/
3683 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3684 uint32 type, uint8 *data, int real_len )
3686 WERROR result = WERR_OK;
3689 /* we must have names on non-zero length */
3691 if ( !key || !*key|| !value || !*value )
3692 return WERR_INVALID_NAME;
3694 /* find the printer key first */
3696 key_index = lookup_printerkey( p2->data, key );
3697 if ( key_index == -1 )
3698 key_index = add_new_printer_key( p2->data, key );
3700 if ( key_index == -1 )
3703 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3704 type, (const char *)data, real_len );
3706 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3707 key, value, type, real_len ));
3712 /****************************************************************************
3713 ***************************************************************************/
3715 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3719 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3722 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3725 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3728 /****************************************************************************
3729 Unpack a list of registry values frem the TDB
3730 ***************************************************************************/
3732 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3737 const char *valuename = NULL;
3738 const char *keyname = NULL;
3742 struct regval_blob *regval_p;
3745 /* add the "PrinterDriverData" key first for performance reasons */
3747 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3749 /* loop and unpack the rest of the registry values */
3753 /* check to see if there are any more registry values */
3756 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3760 /* unpack the next regval */
3762 len += tdb_unpack(buf+len, buflen-len, "fdB",
3768 /* lookup for subkey names which have a type of REG_NONE */
3769 /* there's no data with this entry */
3771 if ( type == REG_NONE ) {
3772 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3773 add_new_printer_key( printer_data, string );
3778 * break of the keyname from the value name.
3779 * Valuenames can have embedded '\'s so be careful.
3780 * only support one level of keys. See the
3781 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3785 str = strchr_m( string, '\\');
3787 /* Put in "PrinterDriverData" is no key specified */
3790 keyname = SPOOL_PRINTERDATA_KEY;
3799 /* see if we need a new key */
3801 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3802 key_index = add_new_printer_key( printer_data, keyname );
3804 if ( key_index == -1 ) {
3805 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3810 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3812 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3813 Thanks to Martin Zielinski for the hint. */
3815 if ( type == REG_BINARY &&
3816 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3817 strequal( valuename, "objectGUID" ) )
3821 /* convert the GUID to a UNICODE string */
3823 memcpy( &guid, data_p, sizeof(struct GUID) );
3825 regval_ctr_addvalue_sz(printer_data->keys[key_index].values,
3827 GUID_string(talloc_tos(), &guid));
3832 regval_ctr_addvalue( printer_data->keys[key_index].values,
3833 valuename, type, (const char *)data_p,
3837 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3844 /****************************************************************************
3845 ***************************************************************************/
3847 static char *win_driver;
3848 static char *os2_driver;
3850 static const char *get_win_driver(void)
3852 if (win_driver == NULL) {
3858 static const char *get_os2_driver(void)
3860 if (os2_driver == NULL) {
3866 static bool set_driver_mapping(const char *from, const char *to)
3868 SAFE_FREE(win_driver);
3869 SAFE_FREE(os2_driver);
3871 win_driver = SMB_STRDUP(from);
3872 os2_driver = SMB_STRDUP(to);
3874 if (win_driver == NULL || os2_driver == NULL) {
3875 SAFE_FREE(win_driver);
3876 SAFE_FREE(os2_driver);
3882 static void map_to_os2_driver(fstring drivername)
3884 char *mapfile = lp_os2_driver_map();
3885 char **lines = NULL;
3889 if (!strlen(drivername))
3895 if (strequal(drivername, get_win_driver())) {
3896 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3897 drivername, get_os2_driver()));
3898 fstrcpy(drivername, get_os2_driver());
3902 lines = file_lines_load(mapfile, &numlines,0,NULL);
3903 if (numlines == 0 || lines == NULL) {
3904 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3909 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3911 for( i = 0; i < numlines; i++) {
3912 char *nt_name = lines[i];
3913 char *os2_name = strchr(nt_name,'=');
3920 while (isspace(*nt_name))
3923 if (!*nt_name || strchr("#;",*nt_name))
3927 int l = strlen(nt_name);
3928 while (l && isspace(nt_name[l-1])) {
3934 while (isspace(*os2_name))
3938 int l = strlen(os2_name);
3939 while (l && isspace(os2_name[l-1])) {
3945 if (strequal(nt_name,drivername)) {
3946 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3947 set_driver_mapping(drivername,os2_name);
3948 fstrcpy(drivername,os2_name);
3960 * @brief Map a Windows driver to a OS/2 driver.
3962 * @param[in] mem_ctx The memory context to use.
3964 * @param[in,out] pdrivername The drivername of Windows to remap.
3966 * @return WERR_OK on success, a corresponding WERROR on failure.
3968 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
3970 const char *mapfile = lp_os2_driver_map();
3971 char **lines = NULL;
3972 const char *drivername;
3976 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
3977 return WERR_INVALID_PARAMETER;
3980 drivername = *pdrivername;
3982 if (mapfile[0] == '\0') {
3983 return WERR_BADFILE;
3986 if (strequal(drivername, get_win_driver())) {
3987 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3988 drivername, get_os2_driver()));
3989 drivername = talloc_strdup(mem_ctx, get_os2_driver());
3990 if (drivername == NULL) {
3993 *pdrivername = drivername;
3997 lines = file_lines_load(mapfile, &numlines, 0, NULL);
3998 if (numlines == 0 || lines == NULL) {
3999 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
4004 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
4006 for( i = 0; i < numlines; i++) {
4007 char *nt_name = lines[i];
4008 char *os2_name = strchr(nt_name, '=');
4010 if (os2_name == NULL) {
4016 while (isspace(*nt_name)) {
4020 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
4025 int l = strlen(nt_name);
4026 while (l && isspace(nt_name[l - 1])) {
4032 while (isspace(*os2_name)) {
4037 int l = strlen(os2_name);
4038 while (l && isspace(os2_name[l-1])) {
4044 if (strequal(nt_name, drivername)) {
4045 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
4046 set_driver_mapping(drivername, os2_name);
4047 drivername = talloc_strdup(mem_ctx, os2_name);
4049 if (drivername == NULL) {
4052 *pdrivername = drivername;
4061 /****************************************************************************
4062 Get a default printer info 2 struct.
4063 ****************************************************************************/
4065 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
4066 const char *servername,
4067 const char* sharename,
4070 int snum = lp_servicenumber(sharename);
4072 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4073 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4074 servername, sharename);
4075 fstrcpy(info->sharename, sharename);
4076 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
4078 /* by setting the driver name to an empty string, a local NT admin
4079 can now run the **local** APW to install a local printer driver
4080 for a Samba shared printer in 2.2. Without this, drivers **must** be
4081 installed on the Samba server for NT clients --jerry */
4082 #if 0 /* JERRY --do not uncomment-- */
4083 if (!*info->drivername)
4084 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
4088 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
4090 strlcpy(info->comment, "", sizeof(info->comment));
4091 fstrcpy(info->printprocessor, "winprint");
4092 fstrcpy(info->datatype, "RAW");
4095 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4096 /* Pull the location and comment strings from cups if we don't
4098 if ( !strlen(info->location) || !strlen(info->comment) ) {
4099 char *comment = NULL;
4100 char *location = NULL;
4101 if (cups_pull_comment_location(info, info->sharename,
4102 &comment, &location)) {
4103 strlcpy(info->comment, comment, sizeof(info->comment));
4104 fstrcpy(info->location, location);
4105 TALLOC_FREE(comment);
4106 TALLOC_FREE(location);
4112 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
4114 info->starttime = 0; /* Minutes since 12:00am GMT */
4115 info->untiltime = 0; /* Minutes since 12:00am GMT */
4117 info->default_priority = 1;
4118 info->setuptime = (uint32)time(NULL);
4121 * I changed this as I think it is better to have a generic
4122 * DEVMODE than to crash Win2k explorer.exe --jerry
4123 * See the HP Deskjet 990c Win2k drivers for an example.
4125 * However the default devmode appears to cause problems
4126 * with the HP CLJ 8500 PCL driver. Hence the addition of
4127 * the "default devmode" parameter --jerry 22/01/2002
4130 if (lp_default_devmode(snum)) {
4131 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
4135 info->devmode = NULL;
4138 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4142 info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
4147 add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
4153 free_nt_devicemode(&info->devmode);
4155 return WERR_ACCESS_DENIED;
4158 /****************************************************************************
4159 ****************************************************************************/
4161 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
4162 const char *servername,
4163 const char *sharename,
4167 int snum = lp_servicenumber(sharename);
4168 TDB_DATA kbuf, dbuf;
4169 fstring printername;
4170 char adevice[MAXDEVICENAME];
4171 char *comment = NULL;
4173 kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4175 dbuf = tdb_fetch(tdb_printers, kbuf);
4177 return get_a_printer_2_default(info, servername,
4178 sharename, get_loc_com);
4181 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4184 &info->default_priority,
4191 &info->c_setprinter,
4201 info->printprocessor,
4206 strlcpy(info->comment, comment, sizeof(info->comment));
4210 /* Samba has to have shared raw drivers. */
4211 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4212 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4214 /* Restore the stripped strings. */
4215 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4217 if ( lp_force_printername(snum) ) {
4218 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4220 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4223 fstrcpy(info->printername, printername);
4226 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4227 /* Pull the location and comment strings from cups if we don't
4229 if ( !strlen(info->location) || !strlen(info->comment) ) {
4230 char *location = NULL;
4232 if (cups_pull_comment_location(info, info->sharename,
4233 &comment, &location)) {
4234 strlcpy(info->comment, comment, sizeof(info->comment));
4235 fstrcpy(info->location, location);
4236 TALLOC_FREE(comment);
4237 TALLOC_FREE(location);
4243 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4246 * Some client drivers freak out if there is a NULL devmode
4247 * (probably the driver is not checking before accessing
4248 * the devmode pointer) --jerry
4250 * See comments in get_a_printer_2_default()
4253 if (lp_default_devmode(snum) && !info->devmode) {
4254 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4256 info->devmode = construct_nt_devicemode(printername);
4259 slprintf( adevice, sizeof(adevice), "%s", info->printername );
4260 if (info->devmode) {
4261 fstrcpy(info->devmode->devicename, adevice);
4264 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4265 DEBUG(0,("unpack_values: talloc() failed!\n"));
4266 SAFE_FREE(dbuf.dptr);
4269 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4271 /* This will get the current RPC talloc context, but we should be
4272 passing this as a parameter... fixme... JRA ! */
4274 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4275 SAFE_FREE(dbuf.dptr);
4279 /* Fix for OS/2 drivers. */
4281 if (get_remote_arch() == RA_OS2) {
4282 map_to_os2_driver(info->drivername);
4285 SAFE_FREE(dbuf.dptr);
4287 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4288 sharename, info->printername, info->drivername));
4293 /****************************************************************************
4294 Debugging function, dump at level 6 the struct in the logs.
4295 ****************************************************************************/
4296 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4299 NT_PRINTER_INFO_LEVEL_2 *info2;
4301 DEBUG(106,("Dumping printer at level [%d]\n", level));
4306 if (printer->info_2 == NULL)
4310 info2=printer->info_2;
4312 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4313 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4314 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4315 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4316 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4317 DEBUGADD(106,("status:[%d]\n", info2->status));
4318 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4319 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4320 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4321 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4322 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4324 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4325 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4326 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4327 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4328 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4329 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4330 DEBUGADD(106,("location:[%s]\n", info2->location));
4331 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4332 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4333 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4334 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4340 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4348 /****************************************************************************
4349 Update the changeid time.
4350 This is SO NASTY as some drivers need this to change, others need it
4351 static. This value will change every second, and I must hope that this
4352 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4354 ****************************************************************************/
4356 static uint32 rev_changeid(void)
4360 get_process_uptime(&tv);
4363 /* Return changeid as msec since spooler restart */
4364 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4367 * This setting seems to work well but is too untested
4368 * to replace the above calculation. Left in for experiementation
4369 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4371 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4377 * The function below are the high level ones.
4378 * only those ones must be called from the spoolss code.
4382 /****************************************************************************
4383 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4384 ****************************************************************************/
4386 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4390 dump_a_printer(printer, level);
4396 * Update the changestamp. Emperical tests show that the
4397 * ChangeID is always updated,but c_setprinter is
4398 * global spooler variable (not per printer).
4401 /* ChangeID **must** be increasing over the lifetime
4402 of client's spoolss service in order for the
4403 client's cache to show updates */
4405 printer->info_2->changeid = rev_changeid();
4408 * Because one day someone will ask:
4409 * NT->NT An admin connection to a remote
4410 * printer show changes imeediately in
4411 * the properities dialog
4413 * A non-admin connection will only show the
4414 * changes after viewing the properites page
4415 * 2 times. Seems to be related to a
4416 * race condition in the client between the spooler
4417 * updating the local cache and the Explorer.exe GUI
4418 * actually displaying the properties.
4420 * This is fixed in Win2k. admin/non-admin
4421 * connections both display changes immediately.
4426 result=update_a_printer_2(printer->info_2);
4430 result=WERR_UNKNOWN_LEVEL;
4437 /****************************************************************************
4438 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4440 Previously the code had a memory allocation problem because it always
4441 used the TALLOC_CTX from the Printer_entry*. This context lasts
4442 as a long as the original handle is open. So if the client made a lot
4443 of getprinter[data]() calls, the memory usage would climb. Now we use
4444 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4445 still use the Printer_entry->ctx for maintaining the cache copy though
4446 since that object must live as long as the handle by definition.
4449 ****************************************************************************/
4451 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4452 const char *sharename, bool get_loc_com)
4457 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4459 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4460 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4466 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4467 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4468 TALLOC_FREE( *pp_printer );
4473 fstrcpy( servername, print_hnd->servername );
4475 fstrcpy( servername, "%L" );
4476 standard_sub_basic( "", "", servername,
4477 sizeof(servername)-1 );
4480 result = get_a_printer_2( (*pp_printer)->info_2,
4481 servername, sharename, get_loc_com);
4483 /* we have a new printer now. Save it with this handle */
4485 if ( !W_ERROR_IS_OK(result) ) {
4486 TALLOC_FREE( *pp_printer );
4487 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4488 sharename, (unsigned int)level, win_errstr(result)));
4492 dump_a_printer( *pp_printer, level);
4497 TALLOC_FREE( *pp_printer );
4498 return WERR_UNKNOWN_LEVEL;
4504 WERROR get_a_printer( Printer_entry *print_hnd,
4505 NT_PRINTER_INFO_LEVEL **pp_printer,
4507 const char *sharename)
4509 return get_a_printer_internal(print_hnd, pp_printer, level,
4513 WERROR get_a_printer_search( Printer_entry *print_hnd,
4514 NT_PRINTER_INFO_LEVEL **pp_printer,
4516 const char *sharename)
4518 return get_a_printer_internal(print_hnd, pp_printer, level,
4522 /****************************************************************************
4523 Deletes a NT_PRINTER_INFO_LEVEL struct.
4524 ****************************************************************************/
4526 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4528 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4535 if ( printer->info_2 )
4536 free_nt_printer_info_level_2(&printer->info_2);
4540 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4544 TALLOC_FREE(*pp_printer);
4549 /****************************************************************************
4550 ****************************************************************************/
4552 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
4553 struct spoolss_DriverInfo8 *_info8)
4555 struct spoolss_DriverInfo8 info8;
4561 info8.version = r->info.info3->version;
4562 info8.driver_name = r->info.info3->driver_name;
4563 info8.architecture = r->info.info3->architecture;
4564 info8.driver_path = r->info.info3->driver_path;
4565 info8.data_file = r->info.info3->data_file;
4566 info8.config_file = r->info.info3->config_file;
4567 info8.help_file = r->info.info3->help_file;
4568 info8.monitor_name = r->info.info3->monitor_name;
4569 info8.default_datatype = r->info.info3->default_datatype;
4570 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
4571 info8.dependent_files = r->info.info3->dependent_files->string;
4575 info8.version = r->info.info6->version;
4576 info8.driver_name = r->info.info6->driver_name;
4577 info8.architecture = r->info.info6->architecture;
4578 info8.driver_path = r->info.info6->driver_path;
4579 info8.data_file = r->info.info6->data_file;
4580 info8.config_file = r->info.info6->config_file;
4581 info8.help_file = r->info.info6->help_file;
4582 info8.monitor_name = r->info.info6->monitor_name;
4583 info8.default_datatype = r->info.info6->default_datatype;
4584 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
4585 info8.dependent_files = r->info.info6->dependent_files->string;
4587 info8.driver_date = r->info.info6->driver_date;
4588 info8.driver_version = r->info.info6->driver_version;
4589 info8.manufacturer_name = r->info.info6->manufacturer_name;
4590 info8.manufacturer_url = r->info.info6->manufacturer_url;
4591 info8.hardware_id = r->info.info6->hardware_id;
4592 info8.provider = r->info.info6->provider;
4595 info8.version = r->info.info8->version;
4596 info8.driver_name = r->info.info8->driver_name;
4597 info8.architecture = r->info.info8->architecture;
4598 info8.driver_path = r->info.info8->driver_path;
4599 info8.data_file = r->info.info8->data_file;
4600 info8.config_file = r->info.info8->config_file;
4601 info8.help_file = r->info.info8->help_file;
4602 info8.monitor_name = r->info.info8->monitor_name;
4603 info8.default_datatype = r->info.info8->default_datatype;
4604 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
4605 info8.dependent_files = r->info.info8->dependent_files->string;
4607 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
4608 info8.previous_names = r->info.info8->previous_names->string;
4610 info8.driver_date = r->info.info8->driver_date;
4611 info8.driver_version = r->info.info8->driver_version;
4612 info8.manufacturer_name = r->info.info8->manufacturer_name;
4613 info8.manufacturer_url = r->info.info8->manufacturer_url;
4614 info8.hardware_id = r->info.info8->hardware_id;
4615 info8.provider = r->info.info8->provider;
4616 info8.print_processor = r->info.info8->print_processor;
4617 info8.vendor_setup = r->info.info8->vendor_setup;
4618 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
4619 info8.color_profiles = r->info.info8->color_profiles->string;
4621 info8.inf_path = r->info.info8->inf_path;
4622 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
4623 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
4624 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
4626 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
4627 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
4639 uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx,
4640 struct spoolss_AddDriverInfoCtr *r,
4644 struct spoolss_DriverInfo8 info8;
4648 DEBUG(10,("adding a printer at level [%d]\n", r->level));
4650 if (!driver_info_ctr_to_info8(r, &info8)) {
4654 *driver_name = talloc_strdup(mem_ctx, info8.driver_name);
4655 if (!*driver_name) {
4658 *version = info8.version;
4660 return add_a_printer_driver_8(&info8);
4663 /****************************************************************************
4664 ****************************************************************************/
4666 WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx,
4667 struct spoolss_DriverInfo8 **driver,
4668 const char *drivername, const char *architecture,
4672 struct spoolss_DriverInfo3 info3;
4673 struct spoolss_DriverInfo8 *info8;
4677 /* Sometime we just want any version of the driver */
4679 if (version == DRIVER_ANY_VERSION) {
4680 /* look for Win2k first and then for NT4 */
4681 result = get_a_printer_driver_3(mem_ctx,
4685 if (!W_ERROR_IS_OK(result)) {
4686 result = get_a_printer_driver_3(mem_ctx,
4692 result = get_a_printer_driver_3(mem_ctx,
4699 if (!W_ERROR_IS_OK(result)) {
4703 info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8);
4708 info8->version = info3.version;
4709 info8->driver_name = info3.driver_name;
4710 info8->architecture = info3.architecture;
4711 info8->driver_path = info3.driver_path;
4712 info8->data_file = info3.data_file;
4713 info8->config_file = info3.config_file;
4714 info8->help_file = info3.help_file;
4715 info8->dependent_files = info3.dependent_files;
4716 info8->monitor_name = info3.monitor_name;
4717 info8->default_datatype = info3.default_datatype;
4724 /****************************************************************************
4725 ****************************************************************************/
4727 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver)
4729 talloc_free(driver);
4734 /****************************************************************************
4735 Determine whether or not a particular driver is currently assigned
4737 ****************************************************************************/
4739 bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r)
4742 int n_services = lp_numservices();
4743 NT_PRINTER_INFO_LEVEL *printer = NULL;
4744 bool in_use = False;
4750 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4752 /* loop through the printers.tdb and check for the drivername */
4754 for (snum=0; snum<n_services && !in_use; snum++) {
4755 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4758 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4761 if (strequal(r->driver_name, printer->info_2->drivername))
4764 free_a_printer( &printer, 2 );
4767 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4770 struct spoolss_DriverInfo8 *d;
4773 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
4775 /* we can still remove the driver if there is one of
4776 "Windows NT x86" version 2 or 3 left */
4778 if (!strequal("Windows NT x86", r->architecture)) {
4779 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION);
4782 switch (r->version) {
4784 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3);
4787 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2);
4790 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4792 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4797 /* now check the error code */
4799 if ( W_ERROR_IS_OK(werr) ) {
4800 /* it's ok to remove the driver, we have other architctures left */
4802 free_a_printer_driver(d);
4806 /* report that the driver is not in use by default */
4812 /**********************************************************************
4813 Check to see if a ogiven file is in use by *info
4814 *********************************************************************/
4816 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
4823 /* mz: skip files that are in the list but already deleted */
4824 if (!file || !file[0]) {
4828 if (strequal(file, info->driver_path))
4831 if (strequal(file, info->data_file))
4834 if (strequal(file, info->config_file))
4837 if (strequal(file, info->help_file))
4840 /* see of there are any dependent files to examine */
4842 if (!info->dependent_files)
4845 while (info->dependent_files[i] && *info->dependent_files[i]) {
4846 if (strequal(file, info->dependent_files[i]))
4855 /**********************************************************************
4856 Utility function to remove the dependent file pointed to by the
4857 input parameter from the list
4858 *********************************************************************/
4860 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
4863 /* bump everything down a slot */
4865 while (files && files[idx+1]) {
4866 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
4875 /**********************************************************************
4876 Check if any of the files used by src are also used by drv
4877 *********************************************************************/
4879 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
4880 struct spoolss_DriverInfo8 *src,
4881 const struct spoolss_DriverInfo8 *drv)
4883 bool in_use = False;
4889 /* check each file. Remove it from the src structure if it overlaps */
4891 if (drv_file_in_use(src->driver_path, drv)) {
4893 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
4894 src->driver_path = talloc_strdup(mem_ctx, "");
4895 if (!src->driver_path) { return false; }
4898 if (drv_file_in_use(src->data_file, drv)) {
4900 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
4901 src->data_file = talloc_strdup(mem_ctx, "");
4902 if (!src->data_file) { return false; }
4905 if (drv_file_in_use(src->config_file, drv)) {
4907 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
4908 src->config_file = talloc_strdup(mem_ctx, "");
4909 if (!src->config_file) { return false; }
4912 if (drv_file_in_use(src->help_file, drv)) {
4914 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
4915 src->help_file = talloc_strdup(mem_ctx, "");
4916 if (!src->help_file) { return false; }
4919 /* are there any dependentfiles to examine? */
4921 if (!src->dependent_files)
4924 while (src->dependent_files[i] && *src->dependent_files[i]) {
4925 if (drv_file_in_use(src->dependent_files[i], drv)) {
4927 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
4928 trim_dependent_file(mem_ctx, src->dependent_files, i);
4936 /****************************************************************************
4937 Determine whether or not a particular driver files are currently being
4938 used by any other driver.
4940 Return value is True if any files were in use by other drivers
4941 and False otherwise.
4943 Upon return, *info has been modified to only contain the driver files
4944 which are not in use
4948 This needs to check all drivers to ensure that all files in use
4949 have been removed from *info, not just the ones in the first
4951 ****************************************************************************/
4953 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
4954 struct spoolss_DriverInfo8 *info)
4959 fstring *list = NULL;
4960 struct spoolss_DriverInfo8 *driver;
4961 bool in_use = false;
4966 version = info->version;
4968 /* loop over all driver versions */
4970 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4972 /* get the list of drivers */
4975 ndrivers = get_ntdrivers(&list, info->architecture, version);
4977 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4978 ndrivers, info->architecture, version));
4980 /* check each driver for overlap in files */
4982 for (i=0; i<ndrivers; i++) {
4983 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4987 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, list[i], info->architecture, version))) {
4992 /* check if d2 uses any files from d1 */
4993 /* only if this is a different driver than the one being deleted */
4995 if (!strequal(info->driver_name, driver->driver_name)) {
4996 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
4997 /* mz: Do not instantly return -
4998 * we need to ensure this file isn't
4999 * also in use by other drivers. */
5004 free_a_printer_driver(driver);
5009 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5014 static NTSTATUS driver_unlink_internals(connection_struct *conn,
5017 struct smb_filename *smb_fname = NULL;
5020 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
5022 if (!NT_STATUS_IS_OK(status)) {
5026 status = unlink_internals(conn, NULL, 0, smb_fname, false);
5028 TALLOC_FREE(smb_fname);
5032 /****************************************************************************
5033 Actually delete the driver files. Make sure that
5034 printer_driver_files_in_use() return False before calling
5036 ****************************************************************************/
5038 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
5039 const struct spoolss_DriverInfo8 *r)
5044 connection_struct *conn;
5047 fstring printdollar;
5048 int printdollar_snum;
5055 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
5056 r->driver_name, r->version));
5058 fstrcpy(printdollar, "print$");
5060 printdollar_snum = find_service(printdollar);
5061 if (printdollar_snum == -1) {
5065 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5066 lp_pathname(printdollar_snum),
5067 rpc_pipe->server_info, &oldcwd);
5068 if (!NT_STATUS_IS_OK(nt_status)) {
5069 DEBUG(0,("delete_driver_files: create_conn_struct "
5070 "returned %s\n", nt_errstr(nt_status)));
5074 if ( !CAN_WRITE(conn) ) {
5075 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5079 /* now delete the files; must strip the '\print$' string from
5082 if (r->driver_path && r->driver_path[0]) {
5083 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
5085 DEBUG(10,("deleting driverfile [%s]\n", s));
5086 driver_unlink_internals(conn, file);
5090 if (r->config_file && r->config_file[0]) {
5091 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
5093 DEBUG(10,("deleting configfile [%s]\n", s));
5094 driver_unlink_internals(conn, file);
5098 if (r->data_file && r->data_file[0]) {
5099 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
5101 DEBUG(10,("deleting datafile [%s]\n", s));
5102 driver_unlink_internals(conn, file);
5106 if (r->help_file && r->help_file[0]) {
5107 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
5109 DEBUG(10,("deleting helpfile [%s]\n", s));
5110 driver_unlink_internals(conn, file);
5114 /* check if we are done removing files */
5116 if (r->dependent_files) {
5117 while (r->dependent_files[i] && r->dependent_files[i][0]) {
5120 /* bypass the "\print$" portion of the path */
5122 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
5124 DEBUG(10,("deleting dependent file [%s]\n", file));
5125 driver_unlink_internals(conn, file);
5137 vfs_ChDir(conn, oldcwd);
5143 /****************************************************************************
5144 Remove a printer driver from the TDB. This assumes that the the driver was
5145 previously looked up.
5146 ***************************************************************************/
5148 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5149 const struct spoolss_DriverInfo8 *r,
5150 uint32 version, bool delete_files )
5156 /* delete the tdb data first */
5158 arch = get_short_archi(r->architecture);
5160 return WERR_UNKNOWN_PRINTER_DRIVER;
5162 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5163 arch, version, r->driver_name) < 0) {
5167 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5168 key, delete_files ? "TRUE" : "FALSE" ));
5170 /* check if the driver actually exists for this environment */
5172 dbuf = tdb_fetch_bystring( tdb_drivers, key );
5174 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5176 return WERR_UNKNOWN_PRINTER_DRIVER;
5179 SAFE_FREE( dbuf.dptr );
5181 /* ok... the driver exists so the delete should return success */
5183 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5184 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5186 return WERR_ACCESS_DENIED;
5190 * now delete any associated files if delete_files == True
5191 * even if this part failes, we return succes because the
5192 * driver doesn not exist any more
5196 delete_driver_files(rpc_pipe, r);
5198 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5204 /****************************************************************************
5205 Store a security desc for a printer.
5206 ****************************************************************************/
5208 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
5210 struct sec_desc_buf *new_secdesc_ctr = NULL;
5211 struct sec_desc_buf *old_secdesc_ctr = NULL;
5212 TALLOC_CTX *mem_ctx = NULL;
5219 mem_ctx = talloc_init("nt_printing_setsec");
5220 if (mem_ctx == NULL)
5223 /* The old owner and group sids of the security descriptor are not
5224 present when new ACEs are added or removed by changing printer
5225 permissions through NT. If they are NULL in the new security
5226 descriptor then copy them over from the old one. */
5228 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5229 struct dom_sid *owner_sid, *group_sid;
5230 struct security_acl *dacl, *sacl;
5231 struct security_descriptor *psd = NULL;
5234 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5235 status = WERR_NOMEM;
5239 /* Pick out correct owner and group sids */
5241 owner_sid = secdesc_ctr->sd->owner_sid ?
5242 secdesc_ctr->sd->owner_sid :
5243 old_secdesc_ctr->sd->owner_sid;
5245 group_sid = secdesc_ctr->sd->group_sid ?
5246 secdesc_ctr->sd->group_sid :
5247 old_secdesc_ctr->sd->group_sid;
5249 dacl = secdesc_ctr->sd->dacl ?
5250 secdesc_ctr->sd->dacl :
5251 old_secdesc_ctr->sd->dacl;
5253 sacl = secdesc_ctr->sd->sacl ?
5254 secdesc_ctr->sd->sacl :
5255 old_secdesc_ctr->sd->sacl;
5257 /* Make a deep copy of the security descriptor */
5259 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5260 owner_sid, group_sid,
5266 status = WERR_NOMEM;
5270 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5273 if (!new_secdesc_ctr) {
5274 new_secdesc_ctr = secdesc_ctr;
5277 /* Store the security descriptor in a tdb */
5279 nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5280 &blob.data, &blob.length);
5281 if (!NT_STATUS_IS_OK(nt_status)) {
5282 status = ntstatus_to_werror(nt_status);
5286 kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5288 dbuf.dptr = (unsigned char *)blob.data;
5289 dbuf.dsize = blob.length;
5291 if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5294 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5295 status = WERR_BADFUNC;
5298 /* Free malloc'ed memory */
5299 talloc_free(blob.data);
5304 talloc_destroy(mem_ctx);
5308 /****************************************************************************
5309 Construct a default security descriptor buffer for a printer.
5310 ****************************************************************************/
5312 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
5314 struct security_ace ace[5]; /* max number of ace entries */
5317 struct security_acl *psa = NULL;
5318 struct sec_desc_buf *sdb = NULL;
5319 struct security_descriptor *psd = NULL;
5320 struct dom_sid adm_sid;
5323 /* Create an ACE where Everyone is allowed to print */
5325 sa = PRINTER_ACE_PRINT;
5326 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5327 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5329 /* Add the domain admins group if we are a DC */
5332 struct dom_sid domadmins_sid;
5334 sid_compose(&domadmins_sid, get_global_sam_sid(),
5337 sa = PRINTER_ACE_FULL_CONTROL;
5338 init_sec_ace(&ace[i++], &domadmins_sid,
5339 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5340 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5341 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5342 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5344 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5345 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
5347 sa = PRINTER_ACE_FULL_CONTROL;
5348 init_sec_ace(&ace[i++], &adm_sid,
5349 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5350 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5351 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5352 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5355 /* add BUILTIN\Administrators as FULL CONTROL */
5357 sa = PRINTER_ACE_FULL_CONTROL;
5358 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5359 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5360 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5361 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5362 SEC_ACE_TYPE_ACCESS_ALLOWED,
5363 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5365 /* Make the security descriptor owned by the BUILTIN\Administrators */
5367 /* The ACL revision number in rpc_secdesc.h differs from the one
5368 created by NT when setting ACE entries in printer
5369 descriptors. NT4 complains about the property being edited by a
5372 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5373 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
5374 &global_sid_Builtin_Administrators,
5375 &global_sid_Builtin_Administrators,
5376 NULL, psa, &sd_size);
5380 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5384 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5386 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5387 (unsigned int)sd_size));
5392 /****************************************************************************
5393 Get a security desc for a printer.
5394 ****************************************************************************/
5396 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
5404 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5405 sharename = temp + 1;
5408 /* Fetch security descriptor from tdb */
5410 kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5412 dbuf = tdb_fetch(tdb_printers, kbuf);
5415 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5417 SAFE_FREE(dbuf.dptr);
5419 if (NT_STATUS_IS_OK(status)) {
5424 *secdesc_ctr = construct_default_printer_sdb(ctx);
5425 if (!*secdesc_ctr) {
5429 status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5430 &blob.data, &blob.length);
5431 if (NT_STATUS_IS_OK(status)) {
5432 dbuf.dptr = (unsigned char *)blob.data;
5433 dbuf.dsize = blob.length;
5434 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5435 talloc_free(blob.data);
5438 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5439 this security descriptor has been created when winbindd was
5440 down. Take ownership of security descriptor. */
5442 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5443 struct dom_sid owner_sid;
5445 /* Change sd owner to workgroup administrator */
5447 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5448 struct sec_desc_buf *new_secdesc_ctr = NULL;
5449 struct security_descriptor *psd = NULL;
5454 sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
5456 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5458 (*secdesc_ctr)->sd->group_sid,
5459 (*secdesc_ctr)->sd->sacl,
5460 (*secdesc_ctr)->sd->dacl,
5467 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5468 if (!new_secdesc_ctr) {
5472 /* Swap with other one */
5474 *secdesc_ctr = new_secdesc_ctr;
5478 nt_printing_setsec(sharename, *secdesc_ctr);
5482 if (DEBUGLEVEL >= 10) {
5483 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
5486 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5487 sharename, the_acl->num_aces));
5489 for (i = 0; i < the_acl->num_aces; i++) {
5490 DEBUG(10, ("%s %d %d 0x%08x\n",
5491 sid_string_dbg(&the_acl->aces[i].trustee),
5492 the_acl->aces[i].type, the_acl->aces[i].flags,
5493 the_acl->aces[i].access_mask));
5502 1: level not implemented
5503 2: file doesn't exist
5504 3: can't allocate memory
5505 4: can't free memory
5506 5: non existant struct
5510 A printer and a printer driver are 2 different things.
5511 NT manages them separatelly, Samba does the same.
5512 Why ? Simply because it's easier and it makes sense !
5514 Now explanation: You have 3 printers behind your samba server,
5515 2 of them are the same make and model (laser A and B). But laser B
5516 has an 3000 sheet feeder and laser A doesn't such an option.
5517 Your third printer is an old dot-matrix model for the accounting :-).
5519 If the /usr/local/samba/lib directory (default dir), you will have
5520 5 files to describe all of this.
5522 3 files for the printers (1 by printer):
5525 NTprinter_accounting
5526 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5527 NTdriver_printer model X
5528 NTdriver_printer model Y
5530 jfm: I should use this comment for the text file to explain
5531 same thing for the forms BTW.
5532 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5536 /* Convert generic access rights to printer object specific access rights.
5537 It turns out that NT4 security descriptors use generic access rights and
5538 NT5 the object specific ones. */
5540 void map_printer_permissions(struct security_descriptor *sd)
5544 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5545 se_map_generic(&sd->dacl->aces[i].access_mask,
5546 &printer_generic_mapping);
5550 void map_job_permissions(struct security_descriptor *sd)
5554 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5555 se_map_generic(&sd->dacl->aces[i].access_mask,
5556 &job_generic_mapping);
5561 /****************************************************************************
5562 Check a user has permissions to perform the given operation. We use the
5563 permission constants defined in include/rpc_spoolss.h to check the various
5564 actions we perform when checking printer access.
5566 PRINTER_ACCESS_ADMINISTER:
5567 print_queue_pause, print_queue_resume, update_printer_sec,
5568 update_printer, spoolss_addprinterex_level_2,
5569 _spoolss_setprinterdata
5574 JOB_ACCESS_ADMINISTER:
5575 print_job_delete, print_job_pause, print_job_resume,
5578 Try access control in the following order (for performance reasons):
5579 1) root and SE_PRINT_OPERATOR can do anything (easy check)
5580 2) check security descriptor (bit comparisons in memory)
5581 3) "printer admins" (may result in numerous calls to winbind)
5583 ****************************************************************************/
5584 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5587 struct sec_desc_buf *secdesc = NULL;
5588 uint32 access_granted;
5591 TALLOC_CTX *mem_ctx = NULL;
5592 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5594 /* If user is NULL then use the current_user structure */
5596 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5598 if (server_info->utok.uid == sec_initial_uid()
5599 || user_has_privileges(server_info->ptok, &se_printop ) ) {
5603 /* Get printer name */
5605 pname = PRINTERNAME(snum);
5607 if (!pname || !*pname) {
5612 /* Get printer security descriptor */
5614 if(!(mem_ctx = talloc_init("print_access_check"))) {
5619 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5620 talloc_destroy(mem_ctx);
5625 if (access_type == JOB_ACCESS_ADMINISTER) {
5626 struct sec_desc_buf *parent_secdesc = secdesc;
5628 /* Create a child security descriptor to check permissions
5629 against. This is because print jobs are child objects
5630 objects of a printer. */
5632 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5634 if (!NT_STATUS_IS_OK(status)) {
5635 talloc_destroy(mem_ctx);
5636 errno = map_errno_from_nt_status(status);
5640 map_job_permissions(secdesc->sd);
5642 map_printer_permissions(secdesc->sd);
5646 status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5649 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5651 /* see if we need to try the printer admin list */
5653 if (!NT_STATUS_IS_OK(status) &&
5654 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5655 NULL, NULL, server_info->ptok,
5656 lp_printer_admin(snum)))) {
5657 talloc_destroy(mem_ctx);
5661 talloc_destroy(mem_ctx);
5663 if (!NT_STATUS_IS_OK(status)) {
5667 return NT_STATUS_IS_OK(status);
5670 /****************************************************************************
5671 Check the time parameters allow a print operation.
5672 *****************************************************************************/
5674 bool print_time_access_check(const char *servicename)
5676 NT_PRINTER_INFO_LEVEL *printer = NULL;
5678 time_t now = time(NULL);
5682 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5685 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5689 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5691 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5694 free_a_printer(&printer, 2);
5702 /****************************************************************************
5703 Fill in the servername sent in the _spoolss_open_printer_ex() call
5704 ****************************************************************************/
5706 char* get_server_name( Printer_entry *printer )
5708 return printer->servername;