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"
26 #include "registry/reg_objects.h"
27 #include "../librpc/gen_ndr/ndr_security.h"
29 static TDB_CONTEXT *tdb_forms; /* used for forms files */
30 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
31 static TDB_CONTEXT *tdb_printers; /* used for printers files */
33 #define FORMS_PREFIX "FORMS/"
34 #define DRIVERS_PREFIX "DRIVERS/"
35 #define PRINTERS_PREFIX "PRINTERS/"
36 #define SECDESC_PREFIX "SECDESC/"
37 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
39 #define NTDRIVERS_DATABASE_VERSION_1 1
40 #define NTDRIVERS_DATABASE_VERSION_2 2
41 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
42 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
43 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
45 /* Map generic permissions to printer object specific permissions */
47 const struct generic_mapping printer_generic_mapping = {
54 const struct standard_mapping printer_std_mapping = {
61 /* Map generic permissions to print server object specific permissions */
63 const struct generic_mapping printserver_generic_mapping = {
70 const struct generic_mapping printserver_std_mapping = {
77 /* Map generic permissions to job object specific permissions */
79 const struct generic_mapping job_generic_mapping = {
86 /* We need one default form to support our default printer. Msoft adds the
87 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
88 array index). Letter is always first, so (for the current code) additions
89 always put things in the correct order. */
90 static const nt_forms_struct default_forms[] = {
91 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
92 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
93 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
94 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
95 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
96 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
97 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
98 {"A0",0x1,0xcd528,0x122488,0x0,0x0,0xcd528,0x122488},
99 {"A1",0x1,0x91050,0xcd528,0x0,0x0,0x91050,0xcd528},
100 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
101 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
102 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
103 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
104 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
105 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
106 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
107 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
108 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
109 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
110 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
111 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
112 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
113 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
114 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
115 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
116 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
117 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
118 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
119 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
120 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
121 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
122 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
123 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
124 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
125 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
126 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
127 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
128 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
129 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
130 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
131 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
132 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
133 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
134 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
135 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
136 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
137 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
138 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
139 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
140 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
141 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
142 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
143 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
144 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
145 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
146 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
147 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
148 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
149 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
150 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
151 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
152 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
153 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
154 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
155 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
156 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
157 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
158 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
159 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
160 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
161 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
162 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
163 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
164 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
165 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
166 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
167 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
168 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
169 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
170 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
171 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
172 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
173 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
174 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
175 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
176 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
177 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
178 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
179 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
180 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
181 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
182 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
183 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
184 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
185 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
186 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
187 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
188 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
189 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
190 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
191 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
192 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
193 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
194 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
195 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
196 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
197 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
198 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
199 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
200 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
201 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
202 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
203 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
204 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
205 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
206 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
207 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
208 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
209 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
210 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
213 static const struct print_architecture_table_node archi_table[]= {
215 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
216 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
217 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
218 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
219 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
220 {"Windows IA64", SPL_ARCH_IA64, 3 },
221 {"Windows x64", SPL_ARCH_X64, 3 },
226 /****************************************************************************
227 generate a new TDB_DATA key for storing a printer
228 ****************************************************************************/
230 static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
236 fstrcpy(share, sharename);
239 keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
240 key = string_term_tdb_data(keystr ? keystr : "");
245 /****************************************************************************
246 generate a new TDB_DATA key for storing a printer security descriptor
247 ****************************************************************************/
249 static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
250 const char* sharename )
256 fstrcpy(share, sharename );
259 keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
260 key = string_term_tdb_data(keystr ? keystr : "");
265 /****************************************************************************
266 ****************************************************************************/
268 static bool upgrade_to_version_3(void)
270 TDB_DATA kbuf, newkey, dbuf;
272 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
274 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
275 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
277 dbuf = tdb_fetch(tdb_drivers, kbuf);
279 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
280 DEBUG(0,("upgrade_to_version_3:moving form\n"));
281 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
282 SAFE_FREE(dbuf.dptr);
283 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
286 if (tdb_delete(tdb_drivers, kbuf) != 0) {
287 SAFE_FREE(dbuf.dptr);
288 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
293 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
294 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
295 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
296 SAFE_FREE(dbuf.dptr);
297 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
300 if (tdb_delete(tdb_drivers, kbuf) != 0) {
301 SAFE_FREE(dbuf.dptr);
302 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
307 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
308 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
309 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
310 SAFE_FREE(dbuf.dptr);
311 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
314 if (tdb_delete(tdb_drivers, kbuf) != 0) {
315 SAFE_FREE(dbuf.dptr);
316 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
321 SAFE_FREE(dbuf.dptr);
327 /*******************************************************************
328 Fix an issue with security descriptors. Printer sec_desc must
329 use more than the generic bits that were previously used
330 in <= 3.0.14a. They must also have a owner and group SID assigned.
331 Otherwise, any printers than have been migrated to a Windows
332 host using printmig.exe will not be accessible.
333 *******************************************************************/
335 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
336 TDB_DATA data, void *state )
339 struct sec_desc_buf *sd_orig = NULL;
340 struct sec_desc_buf *sd_new, *sd_store;
341 struct security_descriptor *sec, *new_sec;
342 TALLOC_CTX *ctx = state;
347 if (!data.dptr || data.dsize == 0) {
351 if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
355 /* upgrade the security descriptor */
357 status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
358 if (!NT_STATUS_IS_OK(status)) {
359 /* delete bad entries */
360 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
361 (const char *)key.dptr ));
362 tdb_delete( tdb_printers, key );
371 /* is this even valid? */
377 /* update access masks */
379 for ( i=0; i<sec->dacl->num_aces; i++ ) {
380 switch ( sec->dacl->aces[i].access_mask ) {
381 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
382 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
385 case GENERIC_ALL_ACCESS:
386 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
389 case READ_CONTROL_ACCESS:
390 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
392 default: /* no change */
397 /* create a new struct security_descriptor with the appropriate owner and group SIDs */
399 new_sec = make_sec_desc( ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
400 &global_sid_Builtin_Administrators,
401 &global_sid_Builtin_Administrators,
402 NULL, NULL, &size_new_sec );
406 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
411 if ( !(sd_store = sec_desc_merge_buf( ctx, sd_new, sd_orig )) ) {
412 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
418 sd_size = ndr_size_security_descriptor(sd_store->sd, 0)
419 + sizeof(struct sec_desc_buf);
421 status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
422 if (!NT_STATUS_IS_OK(status)) {
423 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
427 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
429 /* 0 to continue and non-zero to stop traversal */
431 return (result == -1);
434 /*******************************************************************
435 *******************************************************************/
437 static bool upgrade_to_version_4(void)
442 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
444 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
447 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
449 talloc_destroy( ctx );
451 return ( result != -1 );
454 /*******************************************************************
455 Fix an issue with security descriptors. Printer sec_desc must
456 use more than the generic bits that were previously used
457 in <= 3.0.14a. They must also have a owner and group SID assigned.
458 Otherwise, any printers than have been migrated to a Windows
459 host using printmig.exe will not be accessible.
460 *******************************************************************/
462 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
463 TDB_DATA data, void *state )
465 TALLOC_CTX *ctx = talloc_tos();
468 if (!data.dptr || data.dsize == 0)
471 /* upgrade printer records and security descriptors */
473 if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
474 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
476 else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
477 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
480 /* ignore this record */
484 /* delete the original record and store under the normalized key */
486 if ( tdb_delete( the_tdb, key ) != 0 ) {
487 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
492 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
493 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
501 /*******************************************************************
502 *******************************************************************/
504 static bool upgrade_to_version_5(void)
509 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
511 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
514 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
516 talloc_destroy( ctx );
518 return ( result != -1 );
521 /****************************************************************************
522 Open the NT printing tdbs. Done once before fork().
523 ****************************************************************************/
525 bool nt_printing_init(struct messaging_context *msg_ctx)
527 const char *vstring = "INFO/version";
531 if ( tdb_drivers && tdb_printers && tdb_forms )
535 tdb_close(tdb_drivers);
536 tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
538 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
539 state_path("ntdrivers.tdb"), strerror(errno) ));
544 tdb_close(tdb_printers);
545 tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
547 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
548 state_path("ntprinters.tdb"), strerror(errno) ));
553 tdb_close(tdb_forms);
554 tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
556 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
557 state_path("ntforms.tdb"), strerror(errno) ));
561 /* handle a Samba upgrade */
563 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
565 DEBUG(10, ("Fresh database\n"));
566 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
567 vers_id = NTDRIVERS_DATABASE_VERSION_5;
570 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
572 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
573 if (!upgrade_to_version_3())
575 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
576 vers_id = NTDRIVERS_DATABASE_VERSION_3;
579 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
580 /* Written on a bigendian machine with old fetch_int code. Save as le. */
581 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
582 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
583 vers_id = NTDRIVERS_DATABASE_VERSION_3;
586 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
587 if ( !upgrade_to_version_4() )
589 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
590 vers_id = NTDRIVERS_DATABASE_VERSION_4;
593 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
594 if ( !upgrade_to_version_5() )
596 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
597 vers_id = NTDRIVERS_DATABASE_VERSION_5;
601 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
602 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
607 update_c_setprinter(True);
610 * register callback to handle updating printers as new
611 * drivers are installed
614 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
615 do_drv_upgrade_printer);
617 /* of course, none of the message callbacks matter if you don't
618 tell messages.c that you interested in receiving PRINT_GENERAL
619 msgs. This is done in serverid_register() */
622 if ( lp_security() == SEC_ADS ) {
623 win_rc = check_published_printers();
624 if (!W_ERROR_IS_OK(win_rc))
625 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
631 /*******************************************************************
632 Function to allow filename parsing "the old way".
633 ********************************************************************/
635 static NTSTATUS driver_unix_convert(connection_struct *conn,
636 const char *old_name,
637 struct smb_filename **smb_fname)
640 TALLOC_CTX *ctx = talloc_tos();
641 char *name = talloc_strdup(ctx, old_name);
644 return NT_STATUS_NO_MEMORY;
647 name = unix_clean_name(ctx, name);
649 return NT_STATUS_NO_MEMORY;
651 trim_string(name,"/","/");
653 status = unix_convert(ctx, conn, name, smb_fname, 0);
654 if (!NT_STATUS_IS_OK(status)) {
655 return NT_STATUS_NO_MEMORY;
661 /*******************************************************************
662 tdb traversal function for counting printers.
663 ********************************************************************/
665 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
666 TDB_DATA data, void *context)
668 int *printer_count = (int*)context;
670 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
672 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
678 /*******************************************************************
679 Update the spooler global c_setprinter. This variable is initialized
680 when the parent smbd starts with the number of existing printers. It
681 is monotonically increased by the current number of printers *after*
682 each add or delete printer RPC. Only Microsoft knows why... JRR020119
683 ********************************************************************/
685 uint32 update_c_setprinter(bool initialize)
688 int32 printer_count = 0;
690 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
692 /* Traverse the tdb, counting the printers */
693 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
695 /* If initializing, set c_setprinter to current printers count
696 * otherwise, bump it by the current printer count
699 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
701 c_setprinter = printer_count;
703 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
704 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
706 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
708 return (uint32)c_setprinter;
711 /*******************************************************************
712 Get the spooler global c_setprinter, accounting for initialization.
713 ********************************************************************/
715 uint32 get_c_setprinter(void)
717 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
719 if (c_setprinter == (int32)-1)
720 c_setprinter = update_c_setprinter(True);
722 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
724 return (uint32)c_setprinter;
727 /****************************************************************************
728 Get builtin form struct list.
729 ****************************************************************************/
731 int get_builtin_ntforms(nt_forms_struct **list)
733 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
737 return ARRAY_SIZE(default_forms);
740 /****************************************************************************
741 get a builtin form struct
742 ****************************************************************************/
744 bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
747 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
748 for (i=0; i<ARRAY_SIZE(default_forms); i++) {
749 if (strequal(form_name,default_forms[i].name)) {
750 DEBUGADD(6,("Found builtin form %s \n", form_name));
751 memcpy(form,&default_forms[i],sizeof(*form));
759 /****************************************************************************
760 get a form struct list.
761 ****************************************************************************/
763 int get_ntforms(nt_forms_struct **list)
765 TDB_DATA kbuf, newkey, dbuf;
766 nt_forms_struct form;
773 for (kbuf = tdb_firstkey(tdb_forms);
775 newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
777 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
780 dbuf = tdb_fetch(tdb_forms, kbuf);
784 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
785 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
786 &i, &form.flag, &form.width, &form.length, &form.left,
787 &form.top, &form.right, &form.bottom);
788 SAFE_FREE(dbuf.dptr);
789 if (ret != dbuf.dsize)
792 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
794 DEBUG(0,("get_ntforms: Realloc fail.\n"));
805 /****************************************************************************
806 write a form struct list
807 ****************************************************************************/
809 int write_ntforms(nt_forms_struct **list, int number)
811 TALLOC_CTX *ctx = talloc_tos();
818 for (i=0;i<number;i++) {
819 /* save index, so list is rebuilt in correct order */
820 len = tdb_pack(NULL, 0, "dddddddd",
821 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
822 (*list)[i].left, (*list)[i].top, (*list)[i].right,
827 buf = TALLOC_ARRAY(ctx, char, len);
831 len = tdb_pack((uint8 *)buf, len, "dddddddd",
832 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
833 (*list)[i].left, (*list)[i].top, (*list)[i].right,
835 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
840 dbuf.dptr = (uint8 *)buf;
841 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
853 /****************************************************************************
854 add a form struct at the end of the list
855 ****************************************************************************/
856 bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count)
862 * NT tries to add forms even when
863 * they are already in the base
864 * only update the values if already present
869 for (n=0; n<*count; n++) {
870 if ( strequal((*list)[n].name, form->form_name) ) {
877 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
878 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
881 fstrcpy((*list)[n].name, form->form_name);
885 (*list)[n].flag = form->flags;
886 (*list)[n].width = form->size.width;
887 (*list)[n].length = form->size.height;
888 (*list)[n].left = form->area.left;
889 (*list)[n].top = form->area.top;
890 (*list)[n].right = form->area.right;
891 (*list)[n].bottom = form->area.bottom;
893 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
894 update ? "updated" : "added", form->form_name));
899 /****************************************************************************
900 Delete a named form struct.
901 ****************************************************************************/
903 bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
910 for (n=0; n<*count; n++) {
911 if (!strncmp((*list)[n].name, del_name, strlen(del_name))) {
912 DEBUG(103, ("delete_a_form, [%s] in list\n", del_name));
918 DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
919 *ret = WERR_INVALID_FORM_NAME;
923 if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
927 if (tdb_delete_bystring(tdb_forms, key) != 0) {
936 /****************************************************************************
937 Update a form struct.
938 ****************************************************************************/
940 void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
944 DEBUG(106, ("[%s]\n", form->form_name));
945 for (n=0; n<count; n++) {
946 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
947 if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name)))
951 if (n==count) return;
953 (*list)[n].flag = form->flags;
954 (*list)[n].width = form->size.width;
955 (*list)[n].length = form->size.height;
956 (*list)[n].left = form->area.left;
957 (*list)[n].top = form->area.top;
958 (*list)[n].right = form->area.right;
959 (*list)[n].bottom = form->area.bottom;
962 /****************************************************************************
963 Get the nt drivers list.
964 Traverse the database and look-up the matching names.
965 ****************************************************************************/
966 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
969 const char *short_archi;
971 TDB_DATA kbuf, newkey;
973 short_archi = get_short_archi(architecture);
978 if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
979 short_archi, version) < 0) {
983 for (kbuf = tdb_firstkey(tdb_drivers);
985 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
987 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
990 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
991 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
996 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
1004 /****************************************************************************
1005 Function to do the mapping between the long architecture name and
1007 ****************************************************************************/
1009 const char *get_short_archi(const char *long_archi)
1013 DEBUG(107,("Getting architecture dependant directory\n"));
1016 } while ( (archi_table[i].long_archi!=NULL ) &&
1017 StrCaseCmp(long_archi, archi_table[i].long_archi) );
1019 if (archi_table[i].long_archi==NULL) {
1020 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1024 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1026 DEBUGADD(108,("index: [%d]\n", i));
1027 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1028 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1030 return archi_table[i].short_archi;
1033 /****************************************************************************
1034 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1035 There are two case to be covered here: PE (Portable Executable) and NE (New
1036 Executable) files. Both files support the same INFO structure, but PE files
1037 store the signature in unicode, and NE files store it as !unicode.
1038 returns -1 on error, 1 on version info found, and 0 on no version info found.
1039 ****************************************************************************/
1041 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1047 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1048 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1049 fname, DOS_HEADER_SIZE));
1053 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1054 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1055 fname, (unsigned long)byte_count));
1056 goto no_version_info;
1059 /* Is this really a DOS header? */
1060 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1061 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1062 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1063 goto no_version_info;
1066 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1067 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1068 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1070 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1071 goto no_version_info;
1074 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1075 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1076 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1077 fname, (unsigned long)byte_count));
1078 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1079 goto no_version_info;
1082 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1083 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1084 unsigned int num_sections;
1085 unsigned int section_table_bytes;
1087 /* Just skip over optional header to get to section table */
1088 if (SMB_VFS_LSEEK(fsp,
1089 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1090 SEEK_CUR) == (SMB_OFF_T)-1) {
1091 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1096 /* get the section table */
1097 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1098 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1099 if (section_table_bytes == 0)
1103 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1104 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1105 fname, section_table_bytes));
1109 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1110 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1111 fname, (unsigned long)byte_count));
1115 /* Iterate the section table looking for the resource section ".rsrc" */
1116 for (i = 0; i < num_sections; i++) {
1117 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1119 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1120 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1121 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1123 if (section_bytes == 0)
1127 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1128 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1129 fname, section_bytes));
1133 /* Seek to the start of the .rsrc section info */
1134 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1135 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1140 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1141 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1142 fname, (unsigned long)byte_count));
1146 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1149 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1150 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1151 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1152 /* Align to next long address */
1153 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1155 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1156 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1157 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1159 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1160 fname, *major, *minor,
1161 (*major>>16)&0xffff, *major&0xffff,
1162 (*minor>>16)&0xffff, *minor&0xffff));
1171 /* Version info not found, fall back to origin date/time */
1172 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1176 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1177 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1178 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1179 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1180 /* At this point, we assume the file is in error. It still could be somthing
1181 * else besides a NE file, but it unlikely at this point. */
1185 /* Allocate a bit more space to speed up things */
1187 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1188 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1189 fname, PE_HEADER_SIZE));
1193 /* This is a HACK! I got tired of trying to sort through the messy
1194 * 'NE' file format. If anyone wants to clean this up please have at
1195 * it, but this works. 'NE' files will eventually fade away. JRR */
1196 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1197 /* Cover case that should not occur in a well formed 'NE' .dll file */
1198 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1200 for(i=0; i<byte_count; i++) {
1201 /* Fast skip past data that can't possibly match */
1202 if (buf[i] != 'V') continue;
1204 /* Potential match data crosses buf boundry, move it to beginning
1205 * of buf, and fill the buf with as much as it will hold. */
1206 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1209 memcpy(buf, &buf[i], byte_count-i);
1210 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1211 (byte_count-i))) < 0) {
1213 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1218 byte_count = bc + (byte_count - i);
1219 if (byte_count<VS_VERSION_INFO_SIZE) break;
1224 /* Check that the full signature string and the magic number that
1225 * follows exist (not a perfect solution, but the chances that this
1226 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1227 * twice, as it is simpler to read the code. */
1228 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1229 /* Compute skip alignment to next long address */
1230 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1231 sizeof(VS_SIGNATURE)) & 3;
1232 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1234 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1235 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1236 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1237 fname, *major, *minor,
1238 (*major>>16)&0xffff, *major&0xffff,
1239 (*minor>>16)&0xffff, *minor&0xffff));
1246 /* Version info not found, fall back to origin date/time */
1247 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1252 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1253 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1254 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1265 /****************************************************************************
1266 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1267 share one or more files. During the MS installation process files are checked
1268 to insure that only a newer version of a shared file is installed over an
1269 older version. There are several possibilities for this comparison. If there
1270 is no previous version, the new one is newer (obviously). If either file is
1271 missing the version info structure, compare the creation date (on Unix use
1272 the modification date). Otherwise chose the numerically larger version number.
1273 ****************************************************************************/
1275 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1277 bool use_version = true;
1281 time_t new_create_time;
1285 time_t old_create_time;
1287 struct smb_filename *smb_fname = NULL;
1288 files_struct *fsp = NULL;
1294 SET_STAT_INVALID(st);
1295 new_create_time = (time_t)0;
1296 old_create_time = (time_t)0;
1298 /* Get file version info (if available) for previous file (if it exists) */
1299 status = driver_unix_convert(conn, old_file, &smb_fname);
1300 if (!NT_STATUS_IS_OK(status)) {
1304 status = SMB_VFS_CREATE_FILE(
1307 0, /* root_dir_fid */
1308 smb_fname, /* fname */
1309 FILE_GENERIC_READ, /* access_mask */
1310 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1311 FILE_OPEN, /* create_disposition*/
1312 0, /* create_options */
1313 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1314 INTERNAL_OPEN_ONLY, /* oplock_request */
1315 0, /* allocation_size */
1316 0, /* private_flags */
1322 if (!NT_STATUS_IS_OK(status)) {
1323 /* Old file not found, so by definition new file is in fact newer */
1324 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
1325 "errno = %d\n", smb_fname_str_dbg(smb_fname),
1331 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1337 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1339 use_version = false;
1340 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1343 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1344 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1345 (long)old_create_time));
1348 close_file(NULL, fsp, NORMAL_CLOSE);
1351 /* Get file version info (if available) for new file */
1352 status = driver_unix_convert(conn, new_file, &smb_fname);
1353 if (!NT_STATUS_IS_OK(status)) {
1357 status = SMB_VFS_CREATE_FILE(
1360 0, /* root_dir_fid */
1361 smb_fname, /* fname */
1362 FILE_GENERIC_READ, /* access_mask */
1363 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1364 FILE_OPEN, /* create_disposition*/
1365 0, /* create_options */
1366 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1367 INTERNAL_OPEN_ONLY, /* oplock_request */
1368 0, /* allocation_size */
1369 0, /* private_flags */
1375 if (!NT_STATUS_IS_OK(status)) {
1376 /* New file not found, this shouldn't occur if the caller did its job */
1377 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
1378 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
1382 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1388 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1390 use_version = false;
1391 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1394 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1395 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1396 (long)new_create_time));
1399 close_file(NULL, fsp, NORMAL_CLOSE);
1402 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1403 /* Compare versions and choose the larger version number */
1404 if (new_major > old_major ||
1405 (new_major == old_major && new_minor > old_minor)) {
1407 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1412 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1418 /* Compare modification time/dates and choose the newest time/date */
1419 if (new_create_time > old_create_time) {
1420 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1425 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1433 close_file(NULL, fsp, NORMAL_CLOSE);
1436 TALLOC_FREE(smb_fname);
1440 /****************************************************************************
1441 Determine the correct cVersion associated with an architecture and driver
1442 ****************************************************************************/
1443 static uint32 get_correct_cversion(struct pipes_struct *p,
1444 const char *architecture,
1445 const char *driverpath_in,
1450 struct smb_filename *smb_fname = NULL;
1451 char *driverpath = NULL;
1452 files_struct *fsp = NULL;
1453 connection_struct *conn = NULL;
1456 fstring printdollar;
1457 int printdollar_snum;
1459 *perr = WERR_INVALID_PARAM;
1461 /* If architecture is Windows 95/98/ME, the version is always 0. */
1462 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1463 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1468 /* If architecture is Windows x64, the version is always 3. */
1469 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1470 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1475 fstrcpy(printdollar, "print$");
1477 printdollar_snum = find_service(printdollar);
1478 if (printdollar_snum == -1) {
1479 *perr = WERR_NO_SUCH_SHARE;
1483 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1484 lp_pathname(printdollar_snum),
1485 p->server_info, &oldcwd);
1486 if (!NT_STATUS_IS_OK(nt_status)) {
1487 DEBUG(0,("get_correct_cversion: create_conn_struct "
1488 "returned %s\n", nt_errstr(nt_status)));
1489 *perr = ntstatus_to_werror(nt_status);
1493 /* Open the driver file (Portable Executable format) and determine the
1494 * deriver the cversion. */
1495 driverpath = talloc_asprintf(talloc_tos(),
1504 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
1505 if (!NT_STATUS_IS_OK(nt_status)) {
1506 *perr = ntstatus_to_werror(nt_status);
1510 nt_status = vfs_file_exist(conn, smb_fname);
1511 if (!NT_STATUS_IS_OK(nt_status)) {
1512 *perr = WERR_BADFILE;
1516 status = SMB_VFS_CREATE_FILE(
1519 0, /* root_dir_fid */
1520 smb_fname, /* fname */
1521 FILE_GENERIC_READ, /* access_mask */
1522 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1523 FILE_OPEN, /* create_disposition*/
1524 0, /* create_options */
1525 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1526 INTERNAL_OPEN_ONLY, /* oplock_request */
1527 0, /* private_flags */
1528 0, /* allocation_size */
1534 if (!NT_STATUS_IS_OK(status)) {
1535 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1536 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1537 *perr = WERR_ACCESS_DENIED;
1544 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1545 if (ret == -1) goto error_exit;
1548 DEBUG(6,("get_correct_cversion: Version info not "
1550 smb_fname_str_dbg(smb_fname)));
1555 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1556 * for more details. Version in this case is not just the version of the
1557 * file, but the version in the sense of kernal mode (2) vs. user mode
1558 * (3) drivers. Other bits of the version fields are the version info.
1561 cversion = major & 0x0000ffff;
1563 case 2: /* WinNT drivers */
1564 case 3: /* Win2K drivers */
1568 DEBUG(6,("get_correct_cversion: cversion "
1569 "invalid [%s] cversion = %d\n",
1570 smb_fname_str_dbg(smb_fname),
1575 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1576 " = 0x%x minor = 0x%x\n",
1577 smb_fname_str_dbg(smb_fname), major, minor));
1580 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1581 smb_fname_str_dbg(smb_fname), cversion));
1588 TALLOC_FREE(smb_fname);
1590 close_file(NULL, fsp, NORMAL_CLOSE);
1593 vfs_ChDir(conn, oldcwd);
1596 if (cversion != -1) {
1602 /****************************************************************************
1603 ****************************************************************************/
1605 #define strip_driver_path(_mem_ctx, _element) do { \
1606 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1607 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1608 W_ERROR_HAVE_NO_MEMORY((_element)); \
1612 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1613 struct pipes_struct *rpc_pipe,
1614 const char *architecture,
1615 const char **driver_path,
1616 const char **data_file,
1617 const char **config_file,
1618 const char **help_file,
1619 struct spoolss_StringArray *dependent_files,
1622 const char *short_architecture;
1627 if (!*driver_path || !*data_file || !*config_file) {
1628 return WERR_INVALID_PARAM;
1631 /* clean up the driver name.
1632 * we can get .\driver.dll
1633 * or worse c:\windows\system\driver.dll !
1635 /* using an intermediate string to not have overlaping memcpy()'s */
1637 strip_driver_path(mem_ctx, *driver_path);
1638 strip_driver_path(mem_ctx, *data_file);
1639 strip_driver_path(mem_ctx, *config_file);
1641 strip_driver_path(mem_ctx, *help_file);
1644 if (dependent_files && dependent_files->string) {
1645 for (i=0; dependent_files->string[i]; i++) {
1646 strip_driver_path(mem_ctx, dependent_files->string[i]);
1650 short_architecture = get_short_archi(architecture);
1651 if (!short_architecture) {
1652 return WERR_UNKNOWN_PRINTER_DRIVER;
1655 /* jfm:7/16/2000 the client always sends the cversion=0.
1656 * The server should check which version the driver is by reading
1657 * the PE header of driver->driverpath.
1659 * For Windows 95/98 the version is 0 (so the value sent is correct)
1660 * For Windows NT (the architecture doesn't matter)
1661 * NT 3.1: cversion=0
1662 * NT 3.5/3.51: cversion=1
1667 *version = get_correct_cversion(rpc_pipe, short_architecture,
1668 *driver_path, &err);
1669 if (*version == -1) {
1676 /****************************************************************************
1677 ****************************************************************************/
1679 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1680 struct pipes_struct *rpc_pipe,
1681 struct spoolss_AddDriverInfoCtr *r)
1685 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
1686 r->info.info3->architecture,
1687 &r->info.info3->driver_path,
1688 &r->info.info3->data_file,
1689 &r->info.info3->config_file,
1690 &r->info.info3->help_file,
1691 r->info.info3->dependent_files,
1692 &r->info.info3->version);
1694 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
1695 r->info.info6->architecture,
1696 &r->info.info6->driver_path,
1697 &r->info.info6->data_file,
1698 &r->info.info6->config_file,
1699 &r->info.info6->help_file,
1700 r->info.info6->dependent_files,
1701 &r->info.info6->version);
1703 return WERR_NOT_SUPPORTED;
1707 /****************************************************************************
1708 This function sucks and should be replaced. JRA.
1709 ****************************************************************************/
1711 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1712 const struct spoolss_AddDriverInfo6 *src)
1714 dst->version = src->version;
1716 dst->driver_name = src->driver_name;
1717 dst->architecture = src->architecture;
1718 dst->driver_path = src->driver_path;
1719 dst->data_file = src->data_file;
1720 dst->config_file = src->config_file;
1721 dst->help_file = src->help_file;
1722 dst->monitor_name = src->monitor_name;
1723 dst->default_datatype = src->default_datatype;
1724 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1725 dst->dependent_files = src->dependent_files;
1728 /****************************************************************************
1729 This function sucks and should be replaced. JRA.
1730 ****************************************************************************/
1732 static void convert_level_8_to_level3(TALLOC_CTX *mem_ctx,
1733 struct spoolss_AddDriverInfo3 *dst,
1734 const struct spoolss_DriverInfo8 *src)
1736 dst->version = src->version;
1737 dst->driver_name = src->driver_name;
1738 dst->architecture = src->architecture;
1739 dst->driver_path = src->driver_path;
1740 dst->data_file = src->data_file;
1741 dst->config_file = src->config_file;
1742 dst->help_file = src->help_file;
1743 dst->monitor_name = src->monitor_name;
1744 dst->default_datatype = src->default_datatype;
1745 if (src->dependent_files) {
1746 dst->dependent_files = talloc_zero(mem_ctx, struct spoolss_StringArray);
1747 if (!dst->dependent_files) return;
1748 dst->dependent_files->string = src->dependent_files;
1750 dst->dependent_files = NULL;
1754 /****************************************************************************
1755 ****************************************************************************/
1757 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1758 connection_struct *conn,
1759 const char *driver_file,
1760 const char *short_architecture,
1761 uint32_t driver_version,
1764 struct smb_filename *smb_fname_old = NULL;
1765 struct smb_filename *smb_fname_new = NULL;
1766 char *old_name = NULL;
1767 char *new_name = NULL;
1771 old_name = talloc_asprintf(mem_ctx, "%s/%s",
1772 short_architecture, driver_file);
1773 W_ERROR_HAVE_NO_MEMORY(old_name);
1775 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1776 short_architecture, driver_version, driver_file);
1777 if (new_name == NULL) {
1778 TALLOC_FREE(old_name);
1782 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1784 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1785 if (!NT_STATUS_IS_OK(status)) {
1790 /* Setup a synthetic smb_filename struct */
1791 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
1792 if (!smb_fname_new) {
1797 smb_fname_new->base_name = new_name;
1799 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1800 "'%s'\n", smb_fname_old->base_name,
1801 smb_fname_new->base_name));
1803 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1804 OPENX_FILE_EXISTS_TRUNCATE |
1805 OPENX_FILE_CREATE_IF_NOT_EXIST,
1808 if (!NT_STATUS_IS_OK(status)) {
1809 DEBUG(0,("move_driver_file_to_download_area: Unable "
1810 "to rename [%s] to [%s]: %s\n",
1811 smb_fname_old->base_name, new_name,
1812 nt_errstr(status)));
1813 ret = WERR_ACCESS_DENIED;
1820 TALLOC_FREE(smb_fname_old);
1821 TALLOC_FREE(smb_fname_new);
1825 WERROR move_driver_to_download_area(struct pipes_struct *p,
1826 struct spoolss_AddDriverInfoCtr *r,
1829 struct spoolss_AddDriverInfo3 *driver;
1830 struct spoolss_AddDriverInfo3 converted_driver;
1831 const char *short_architecture;
1832 struct smb_filename *smb_dname = NULL;
1833 char *new_dir = NULL;
1834 connection_struct *conn = NULL;
1837 TALLOC_CTX *ctx = talloc_tos();
1840 fstring printdollar;
1841 int printdollar_snum;
1847 driver = r->info.info3;
1850 convert_level_6_to_level3(&converted_driver, r->info.info6);
1851 driver = &converted_driver;
1854 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1855 return WERR_UNKNOWN_LEVEL;
1858 short_architecture = get_short_archi(driver->architecture);
1859 if (!short_architecture) {
1860 return WERR_UNKNOWN_PRINTER_DRIVER;
1863 fstrcpy(printdollar, "print$");
1865 printdollar_snum = find_service(printdollar);
1866 if (printdollar_snum == -1) {
1867 *perr = WERR_NO_SUCH_SHARE;
1868 return WERR_NO_SUCH_SHARE;
1871 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1872 lp_pathname(printdollar_snum),
1873 p->server_info, &oldcwd);
1874 if (!NT_STATUS_IS_OK(nt_status)) {
1875 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1876 "returned %s\n", nt_errstr(nt_status)));
1877 *perr = ntstatus_to_werror(nt_status);
1881 new_dir = talloc_asprintf(ctx,
1889 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1890 if (!NT_STATUS_IS_OK(nt_status)) {
1895 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1897 create_directory(conn, NULL, smb_dname);
1899 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1900 * listed for this driver which has already been moved, skip it (note:
1901 * drivers may list the same file name several times. Then check if the
1902 * file already exists in archi\version\, if so, check that the version
1903 * info (or time stamps if version info is unavailable) is newer (or the
1904 * date is later). If it is, move it to archi\version\filexxx.yyy.
1905 * Otherwise, delete the file.
1907 * If a file is not moved to archi\version\ because of an error, all the
1908 * rest of the 'unmoved' driver files are removed from archi\. If one or
1909 * more of the driver's files was already moved to archi\version\, it
1910 * potentially leaves the driver in a partially updated state. Version
1911 * trauma will most likely occur if an client attempts to use any printer
1912 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1913 * done is appropriate... later JRR
1916 DEBUG(5,("Moving files now !\n"));
1918 if (driver->driver_path && strlen(driver->driver_path)) {
1920 *perr = move_driver_file_to_download_area(ctx,
1922 driver->driver_path,
1926 if (!W_ERROR_IS_OK(*perr)) {
1927 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1934 if (driver->data_file && strlen(driver->data_file)) {
1935 if (!strequal(driver->data_file, driver->driver_path)) {
1937 *perr = move_driver_file_to_download_area(ctx,
1943 if (!W_ERROR_IS_OK(*perr)) {
1944 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1952 if (driver->config_file && strlen(driver->config_file)) {
1953 if (!strequal(driver->config_file, driver->driver_path) &&
1954 !strequal(driver->config_file, driver->data_file)) {
1956 *perr = move_driver_file_to_download_area(ctx,
1958 driver->config_file,
1962 if (!W_ERROR_IS_OK(*perr)) {
1963 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1971 if (driver->help_file && strlen(driver->help_file)) {
1972 if (!strequal(driver->help_file, driver->driver_path) &&
1973 !strequal(driver->help_file, driver->data_file) &&
1974 !strequal(driver->help_file, driver->config_file)) {
1976 *perr = move_driver_file_to_download_area(ctx,
1982 if (!W_ERROR_IS_OK(*perr)) {
1983 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1991 if (driver->dependent_files && driver->dependent_files->string) {
1992 for (i=0; driver->dependent_files->string[i]; i++) {
1993 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1994 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1995 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1996 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1998 for (j=0; j < i; j++) {
1999 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
2004 *perr = move_driver_file_to_download_area(ctx,
2006 driver->dependent_files->string[i],
2010 if (!W_ERROR_IS_OK(*perr)) {
2011 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
2022 TALLOC_FREE(smb_dname);
2025 vfs_ChDir(conn, oldcwd);
2029 if (W_ERROR_EQUAL(*perr, WERR_OK)) {
2033 return WERR_UNKNOWN_PRINTER_DRIVER;
2038 /****************************************************************************
2039 ****************************************************************************/
2041 static uint32 add_a_printer_driver_3(struct spoolss_AddDriverInfo3 *driver)
2043 TALLOC_CTX *ctx = talloc_tos();
2045 const char *architecture;
2046 char *directory = NULL;
2052 architecture = get_short_archi(driver->architecture);
2053 if (!architecture) {
2057 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2058 * \\server is added in the rpc server layer.
2059 * It does make sense to NOT store the server's name in the printer TDB.
2062 directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
2063 architecture, driver->version);
2068 #define gen_full_driver_unc_path(ctx, directory, file) \
2070 if (file && strlen(file)) { \
2071 file = talloc_asprintf(ctx, "%s%s", directory, file); \
2073 file = talloc_strdup(ctx, ""); \
2076 return (uint32_t)-1; \
2080 /* .inf files do not always list a file for each of the four standard files.
2081 * Don't prepend a path to a null filename, or client claims:
2082 * "The server on which the printer resides does not have a suitable
2083 * <printer driver name> printer driver installed. Click OK if you
2084 * wish to install the driver on your local machine."
2087 gen_full_driver_unc_path(ctx, directory, driver->driver_path);
2088 gen_full_driver_unc_path(ctx, directory, driver->data_file);
2089 gen_full_driver_unc_path(ctx, directory, driver->config_file);
2090 gen_full_driver_unc_path(ctx, directory, driver->help_file);
2092 if (driver->dependent_files && driver->dependent_files->string) {
2093 for (i=0; driver->dependent_files->string[i]; i++) {
2094 gen_full_driver_unc_path(ctx, directory,
2095 driver->dependent_files->string[i]);
2099 key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
2100 architecture, driver->version, driver->driver_name);
2105 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
2112 len += tdb_pack(buf+len, buflen-len, "dffffffff",
2114 driver->driver_name,
2115 driver->architecture,
2116 driver->driver_path,
2118 driver->config_file,
2120 driver->monitor_name ? driver->monitor_name : "",
2121 driver->default_datatype ? driver->default_datatype : "");
2123 if (driver->dependent_files && driver->dependent_files->string) {
2124 for (i=0; driver->dependent_files->string[i]; i++) {
2125 len += tdb_pack(buf+len, buflen-len, "f",
2126 driver->dependent_files->string[i]);
2130 if (len != buflen) {
2131 buf = (uint8 *)SMB_REALLOC(buf, len);
2133 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2144 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2148 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2154 /****************************************************************************
2155 ****************************************************************************/
2157 static uint32_t add_a_printer_driver_8(struct spoolss_DriverInfo8 *driver)
2159 TALLOC_CTX *mem_ctx = talloc_new(talloc_tos());
2160 struct spoolss_AddDriverInfo3 info3;
2163 convert_level_8_to_level3(mem_ctx, &info3, driver);
2165 ret = add_a_printer_driver_3(&info3);
2166 talloc_free(mem_ctx);
2171 /****************************************************************************
2172 ****************************************************************************/
2174 static WERROR get_a_printer_driver_3_default(TALLOC_CTX *mem_ctx,
2175 struct spoolss_DriverInfo3 *info,
2176 const char *driver, const char *arch)
2178 info->driver_name = talloc_strdup(mem_ctx, driver);
2179 if (!info->driver_name) {
2183 info->default_datatype = talloc_strdup(mem_ctx, "RAW");
2184 if (!info->default_datatype) {
2188 info->driver_path = talloc_strdup(mem_ctx, "");
2189 info->data_file = talloc_strdup(mem_ctx, "");
2190 info->config_file = talloc_strdup(mem_ctx, "");
2191 info->help_file = talloc_strdup(mem_ctx, "");
2192 if (!info->driver_path || !info->data_file || !info->config_file || !info->help_file) {
2199 /****************************************************************************
2200 ****************************************************************************/
2202 static WERROR get_a_printer_driver_3(TALLOC_CTX *mem_ctx,
2203 struct spoolss_DriverInfo3 *driver,
2204 const char *drivername, const char *arch,
2208 const char *architecture;
2212 fstring name, driverpath, environment, datafile, configfile, helpfile, monitorname, defaultdatatype;
2214 architecture = get_short_archi(arch);
2215 if ( !architecture ) {
2216 return WERR_UNKNOWN_PRINTER_DRIVER;
2219 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2221 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2224 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2226 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
2227 architecture, version, drivername) < 0) {
2231 dbuf = tdb_fetch_bystring(tdb_drivers, key);
2234 return WERR_UNKNOWN_PRINTER_DRIVER;
2237 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2248 driver->driver_name = talloc_strdup(mem_ctx, name);
2249 driver->architecture = talloc_strdup(mem_ctx, environment);
2250 driver->driver_path = talloc_strdup(mem_ctx, driverpath);
2251 driver->data_file = talloc_strdup(mem_ctx, datafile);
2252 driver->config_file = talloc_strdup(mem_ctx, configfile);
2253 driver->help_file = talloc_strdup(mem_ctx, helpfile);
2254 driver->monitor_name = talloc_strdup(mem_ctx, monitorname);
2255 driver->default_datatype = talloc_strdup(mem_ctx, defaultdatatype);
2259 while (len < dbuf.dsize) {
2263 driver->dependent_files = talloc_realloc(mem_ctx, driver->dependent_files, const char *, i+2);
2264 if (!driver->dependent_files ) {
2265 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2269 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2272 driver->dependent_files[i] = talloc_strdup(mem_ctx, file);
2277 if (driver->dependent_files)
2278 driver->dependent_files[i] = NULL;
2280 SAFE_FREE(dbuf.dptr);
2283 if (len != dbuf.dsize) {
2284 return get_a_printer_driver_3_default(mem_ctx, driver, drivername, arch);
2290 /****************************************************************************
2291 ****************************************************************************/
2292 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2296 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2301 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2302 nt_devmode->devicename,
2303 nt_devmode->formname,
2305 nt_devmode->specversion,
2306 nt_devmode->driverversion,
2308 nt_devmode->driverextra,
2309 nt_devmode->orientation,
2310 nt_devmode->papersize,
2311 nt_devmode->paperlength,
2312 nt_devmode->paperwidth,
2315 nt_devmode->defaultsource,
2316 nt_devmode->printquality,
2319 nt_devmode->yresolution,
2320 nt_devmode->ttoption,
2321 nt_devmode->collate,
2322 nt_devmode->logpixels,
2325 nt_devmode->bitsperpel,
2326 nt_devmode->pelswidth,
2327 nt_devmode->pelsheight,
2328 nt_devmode->displayflags,
2329 nt_devmode->displayfrequency,
2330 nt_devmode->icmmethod,
2331 nt_devmode->icmintent,
2332 nt_devmode->mediatype,
2333 nt_devmode->dithertype,
2334 nt_devmode->reserved1,
2335 nt_devmode->reserved2,
2336 nt_devmode->panningwidth,
2337 nt_devmode->panningheight,
2338 nt_devmode->nt_dev_private);
2340 if (nt_devmode->nt_dev_private) {
2341 len += tdb_pack(buf+len, buflen-len, "B",
2342 nt_devmode->driverextra,
2343 nt_devmode->nt_dev_private);
2346 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2351 /****************************************************************************
2352 Pack all values in all printer keys
2353 ***************************************************************************/
2355 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2359 struct regval_blob *val;
2360 struct regval_ctr *val_ctr;
2367 /* loop over all keys */
2369 for ( i=0; i<data->num_keys; i++ ) {
2370 val_ctr = data->keys[i].values;
2371 num_values = regval_ctr_numvals( val_ctr );
2373 /* pack the keyname followed by a empty value */
2375 len += tdb_pack(buf+len, buflen-len, "pPdB",
2376 &data->keys[i].name,
2382 /* now loop over all values */
2384 for ( j=0; j<num_values; j++ ) {
2385 /* pathname should be stored as <key>\<value> */
2387 val = regval_ctr_specific_value( val_ctr, j );
2388 if (asprintf(&path, "%s\\%s",
2390 regval_name(val)) < 0) {
2394 len += tdb_pack(buf+len, buflen-len, "pPdB",
2399 regval_data_p(val) );
2401 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2409 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2415 /****************************************************************************
2416 Delete a printer - this just deletes the printer info file, any open
2417 handles are not affected.
2418 ****************************************************************************/
2420 uint32 del_a_printer(const char *sharename)
2423 char *printdb_path = NULL;
2424 TALLOC_CTX *ctx = talloc_tos();
2426 kbuf = make_printer_tdbkey(ctx, sharename);
2427 tdb_delete(tdb_printers, kbuf);
2429 kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2430 tdb_delete(tdb_printers, kbuf);
2432 close_all_print_db();
2434 if (geteuid() == sec_initial_uid()) {
2435 if (asprintf(&printdb_path, "%s%s.tdb",
2436 cache_path("printing/"),
2440 unlink(printdb_path);
2441 SAFE_FREE(printdb_path);
2447 /****************************************************************************
2448 ****************************************************************************/
2449 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2455 TDB_DATA kbuf, dbuf;
2458 * in addprinter: no servername and the printer is the name
2459 * in setprinter: servername is \\server
2460 * and printer is \\server\\printer
2462 * Samba manages only local printers.
2463 * we currently don't support things like i
2464 * path=\\other_server\printer
2466 * We only store the printername, not \\server\printername
2469 if ( info->servername[0] != '\0' ) {
2470 trim_string(info->printername, info->servername, NULL);
2471 trim_char(info->printername, '\\', '\0');
2472 info->servername[0]='\0';
2476 * JFM: one day I'll forget.
2477 * below that's info->portname because that's the SAMBA sharename
2478 * and I made NT 'thinks' it's the portname
2479 * the info->sharename is the thing you can name when you add a printer
2480 * that's the short-name when you create shared printer for 95/98
2481 * So I've made a limitation in SAMBA: you can only have 1 printer model
2482 * behind a SAMBA share.
2490 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2493 info->default_priority,
2510 info->printprocessor,
2514 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2515 retlen = pack_values( info->data, buf+len, buflen-len );
2522 if (buflen != len) {
2523 buf = (uint8 *)SMB_REALLOC(buf, len);
2525 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2533 kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2538 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2541 if (!W_ERROR_IS_OK(ret))
2542 DEBUG(8, ("error updating printer to tdb on disk\n"));
2546 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2547 info->sharename, info->drivername, info->portname, len));
2552 /****************************************************************************
2553 Create and allocate a default devicemode.
2554 ****************************************************************************/
2556 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
2557 const char *devicename,
2558 struct spoolss_DeviceMode **devmode)
2560 struct spoolss_DeviceMode *dm;
2563 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2568 dname = talloc_asprintf(dm, "%s", devicename);
2569 if (dname == NULL) {
2572 if (strlen(dname) > MAXDEVICENAME) {
2573 dname[MAXDEVICENAME] = '\0';
2575 dm->devicename = dname;
2577 dm->formname = talloc_strdup(dm, "Letter");
2578 if (dm->formname == NULL) {
2582 dm->specversion = DMSPEC_NT4_AND_ABOVE;
2583 dm->driverversion = 0x0400;
2585 dm->__driverextra_length = 0;
2586 dm->fields = DEVMODE_FORMNAME |
2588 DEVMODE_PRINTQUALITY |
2589 DEVMODE_DEFAULTSOURCE |
2593 DEVMODE_ORIENTATION;
2594 dm->orientation = DMORIENT_PORTRAIT;
2595 dm->papersize = DMPAPER_LETTER;
2596 dm->paperlength = 0;
2600 dm->defaultsource = DMBIN_FORMSOURCE;
2601 dm->printquality = DMRES_HIGH; /* 0x0258 */
2602 dm->color = DMRES_MONOCHROME;
2603 dm->duplex = DMDUP_SIMPLEX;
2604 dm->yresolution = 0;
2605 dm->ttoption = DMTT_SUBDEV;
2606 dm->collate = DMCOLLATE_FALSE;
2616 dm->displayflags = 0;
2617 dm->displayfrequency = 0;
2620 dm->panningwidth = 0;
2621 dm->panningheight = 0;
2623 dm->driverextra_data.data = NULL;
2624 dm->driverextra_data.length = 0;
2630 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
2631 struct spoolss_security_descriptor **secdesc)
2633 struct security_ace ace[5]; /* max number of ace entries */
2636 struct security_acl *psa = NULL;
2637 struct security_descriptor *psd = NULL;
2638 struct dom_sid adm_sid;
2641 /* Create an ACE where Everyone is allowed to print */
2643 sa = PRINTER_ACE_PRINT;
2644 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2645 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2647 /* Add the domain admins group if we are a DC */
2650 struct dom_sid domadmins_sid;
2652 sid_compose(&domadmins_sid, get_global_sam_sid(),
2655 sa = PRINTER_ACE_FULL_CONTROL;
2656 init_sec_ace(&ace[i++], &domadmins_sid,
2657 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2658 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2659 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2660 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2662 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
2663 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
2665 sa = PRINTER_ACE_FULL_CONTROL;
2666 init_sec_ace(&ace[i++], &adm_sid,
2667 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2668 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2669 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2670 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2673 /* add BUILTIN\Administrators as FULL CONTROL */
2675 sa = PRINTER_ACE_FULL_CONTROL;
2676 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2677 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2678 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2679 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2680 SEC_ACE_TYPE_ACCESS_ALLOWED,
2681 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2683 /* Make the security descriptor owned by the BUILTIN\Administrators */
2685 /* The ACL revision number in rpc_secdesc.h differs from the one
2686 created by NT when setting ACE entries in printer
2687 descriptors. NT4 complains about the property being edited by a
2690 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
2691 psd = make_sec_desc(mem_ctx,
2693 SEC_DESC_SELF_RELATIVE,
2694 &global_sid_Builtin_Administrators,
2695 &global_sid_Builtin_Administrators,
2702 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2706 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2707 (unsigned int)sd_size));
2714 /****************************************************************************
2715 Malloc and return an NT devicemode.
2716 ****************************************************************************/
2718 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2721 char adevice[MAXDEVICENAME];
2722 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2724 if (nt_devmode == NULL) {
2725 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2729 ZERO_STRUCTP(nt_devmode);
2731 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2732 fstrcpy(nt_devmode->devicename, adevice);
2734 fstrcpy(nt_devmode->formname, "Letter");
2736 nt_devmode->specversion = DMSPEC_NT4_AND_ABOVE;
2737 nt_devmode->driverversion = 0x0400;
2738 nt_devmode->size = 0x00DC;
2739 nt_devmode->driverextra = 0x0000;
2740 nt_devmode->fields = DEVMODE_FORMNAME |
2742 DEVMODE_PRINTQUALITY |
2743 DEVMODE_DEFAULTSOURCE |
2747 DEVMODE_ORIENTATION;
2748 nt_devmode->orientation = DMORIENT_PORTRAIT;
2749 nt_devmode->papersize = DMPAPER_LETTER;
2750 nt_devmode->paperlength = 0;
2751 nt_devmode->paperwidth = 0;
2752 nt_devmode->scale = 0x64;
2753 nt_devmode->copies = 1;
2754 nt_devmode->defaultsource = DMBIN_FORMSOURCE;
2755 nt_devmode->printquality = DMRES_HIGH; /* 0x0258 */
2756 nt_devmode->color = DMRES_MONOCHROME;
2757 nt_devmode->duplex = DMDUP_SIMPLEX;
2758 nt_devmode->yresolution = 0;
2759 nt_devmode->ttoption = DMTT_SUBDEV;
2760 nt_devmode->collate = DMCOLLATE_FALSE;
2761 nt_devmode->icmmethod = 0;
2762 nt_devmode->icmintent = 0;
2763 nt_devmode->mediatype = 0;
2764 nt_devmode->dithertype = 0;
2766 /* non utilisés par un driver d'imprimante */
2767 nt_devmode->logpixels = 0;
2768 nt_devmode->bitsperpel = 0;
2769 nt_devmode->pelswidth = 0;
2770 nt_devmode->pelsheight = 0;
2771 nt_devmode->displayflags = 0;
2772 nt_devmode->displayfrequency = 0;
2773 nt_devmode->reserved1 = 0;
2774 nt_devmode->reserved2 = 0;
2775 nt_devmode->panningwidth = 0;
2776 nt_devmode->panningheight = 0;
2778 nt_devmode->nt_dev_private = NULL;
2782 /****************************************************************************
2783 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2784 ****************************************************************************/
2786 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2788 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2790 if(nt_devmode == NULL)
2793 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2795 SAFE_FREE(nt_devmode->nt_dev_private);
2796 SAFE_FREE(*devmode_ptr);
2799 /****************************************************************************
2800 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2801 ****************************************************************************/
2803 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2805 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2810 free_nt_devicemode(&info->devmode);
2812 TALLOC_FREE( *info_ptr );
2816 /****************************************************************************
2817 ****************************************************************************/
2818 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2822 NT_DEVICEMODE devmode;
2824 ZERO_STRUCT(devmode);
2826 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2828 if (!*nt_devmode) return len;
2830 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2834 &devmode.specversion,
2835 &devmode.driverversion,
2837 &devmode.driverextra,
2838 &devmode.orientation,
2840 &devmode.paperlength,
2841 &devmode.paperwidth,
2844 &devmode.defaultsource,
2845 &devmode.printquality,
2848 &devmode.yresolution,
2854 &devmode.bitsperpel,
2856 &devmode.pelsheight,
2857 &devmode.displayflags,
2858 &devmode.displayfrequency,
2862 &devmode.dithertype,
2865 &devmode.panningwidth,
2866 &devmode.panningheight,
2867 &devmode.nt_dev_private);
2869 if (devmode.nt_dev_private) {
2870 /* the len in tdb_unpack is an int value and
2871 * devmode.driverextra is only a short
2873 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2874 devmode.driverextra=(uint16)extra_len;
2876 /* check to catch an invalid TDB entry so we don't segfault */
2877 if (devmode.driverextra == 0) {
2878 devmode.nt_dev_private = NULL;
2882 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2884 SAFE_FREE(devmode.nt_dev_private);
2888 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2889 if (devmode.nt_dev_private)
2890 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2895 /****************************************************************************
2896 Allocate and initialize a new slot.
2897 ***************************************************************************/
2899 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2905 if ( !name || !data )
2908 /* allocate another slot in the NT_PRINTER_KEY array */
2910 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2911 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2917 key_index = data->num_keys;
2919 /* initialze new key */
2921 data->keys[key_index].name = talloc_strdup( data, name );
2923 werr = regval_ctr_init(data, &(data->keys[key_index].values));
2924 if (!W_ERROR_IS_OK(werr)) {
2930 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2935 /****************************************************************************
2936 search for a registry key name in the existing printer data
2937 ***************************************************************************/
2939 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2943 for ( i=0; i<data->num_keys; i++ ) {
2944 if ( strequal( data->keys[i].name, name ) ) {
2946 /* cleanup memory */
2948 TALLOC_FREE( data->keys[i].name );
2949 TALLOC_FREE( data->keys[i].values );
2951 /* if not the end of the array, move remaining elements down one slot */
2954 if ( data->num_keys && (i < data->num_keys) )
2955 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2962 return data->num_keys;
2965 /****************************************************************************
2966 search for a registry key name in the existing printer data
2967 ***************************************************************************/
2969 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2974 if ( !data || !name )
2977 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2979 /* loop over all existing keys */
2981 for ( i=0; i<data->num_keys; i++ ) {
2982 if ( strequal(data->keys[i].name, name) ) {
2983 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2993 /****************************************************************************
2994 ***************************************************************************/
2996 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
3000 int num_subkeys = 0;
3002 fstring *subkeys_ptr = NULL;
3013 /* special case of asking for the top level printer data registry key names */
3015 if ( strlen(key) == 0 ) {
3016 for ( i=0; i<data->num_keys; i++ ) {
3018 /* found a match, so allocate space and copy the name */
3020 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3021 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3026 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
3033 /* asking for the subkeys of some key */
3034 /* subkey paths are stored in the key name using '\' as the delimiter */
3036 for ( i=0; i<data->num_keys; i++ ) {
3037 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
3039 /* if we found the exact key, then break */
3040 key_len = strlen( key );
3041 if ( strlen(data->keys[i].name) == key_len )
3044 /* get subkey path */
3046 p = data->keys[i].name + key_len;
3049 fstrcpy( subkeyname, p );
3050 if ( (p = strchr( subkeyname, '\\' )) )
3053 /* don't add a key more than once */
3055 for ( j=0; j<num_subkeys; j++ ) {
3056 if ( strequal( subkeys_ptr[j], subkeyname ) )
3060 if ( j != num_subkeys )
3063 /* found a match, so allocate space and copy the name */
3065 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3066 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3071 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
3077 /* return error if the key was not found */
3079 if ( i == data->num_keys ) {
3080 SAFE_FREE(subkeys_ptr);
3085 /* tag off the end */
3088 fstrcpy(subkeys_ptr[num_subkeys], "" );
3090 *subkeys = subkeys_ptr;
3096 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3099 regval_ctr_delvalue(ctr, val_name);
3100 regval_ctr_addvalue_sz(ctr, val_name, sz);
3103 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
3106 regval_ctr_delvalue(ctr, val_name);
3107 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
3108 (uint8 *) &dword, sizeof(dword));
3111 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
3114 uint8 bin_bool = (b ? 1 : 0);
3115 regval_ctr_delvalue(ctr, val_name);
3116 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
3117 (uint8 *) &bin_bool, sizeof(bin_bool));
3120 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3121 const char *multi_sz)
3128 regval_ctr_delvalue(ctr, val_name);
3129 regval_ctr_addvalue_multi_sz(ctr, val_name, a);
3132 /****************************************************************************
3133 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3135 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3136 * @return bool indicating success or failure
3137 ***************************************************************************/
3139 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
3141 struct regval_ctr *ctr = NULL;
3143 const char *dnssuffix;
3144 char *allocated_string = NULL;
3145 const char *ascii_str;
3148 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3149 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3150 ctr = info2->data->keys[i].values;
3152 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3153 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3155 /* we make the assumption that the netbios name is the same
3156 as the DNS name sinc ethe former will be what we used to
3159 dnssuffix = get_mydnsdomname(talloc_tos());
3160 if (dnssuffix && *dnssuffix) {
3161 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3163 fstrcpy( longname, global_myname() );
3166 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3168 if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3171 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3172 SAFE_FREE(allocated_string);
3174 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3175 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3176 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3177 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3178 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3179 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3180 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3181 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3182 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3184 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3185 (info2->attributes &
3186 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3188 switch (info2->attributes & 0x3) {
3190 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3193 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3196 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3199 ascii_str = "unknown";
3201 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3206 /*****************************************************************
3207 ****************************************************************/
3209 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3213 struct regval_ctr *ctr=NULL;
3215 /* find the DsSpooler key */
3216 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3217 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3218 ctr = info2->data->keys[i].values;
3220 regval_ctr_delvalue(ctr, "objectGUID");
3222 /* We used to store this as a REG_BINARY but that causes
3225 regval_ctr_addvalue_sz(ctr, "objectGUID",
3226 GUID_string(talloc_tos(), &guid));
3229 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3230 NT_PRINTER_INFO_LEVEL *printer)
3234 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3235 char *srv_dn_utf8, **srv_cn_utf8;
3238 const char *attrs[] = {"objectGUID", NULL};
3240 WERROR win_rc = WERR_OK;
3241 size_t converted_size;
3243 /* build the ads mods */
3244 ctx = talloc_init("nt_printer_publish_ads");
3249 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3251 /* figure out where to publish */
3252 ads_find_machine_acct(ads, &res, global_myname());
3254 /* We use ldap_get_dn here as we need the answer
3255 * in utf8 to call ldap_explode_dn(). JRA. */
3257 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3260 return WERR_SERVER_UNAVAILABLE;
3262 ads_msgfree(ads, res);
3263 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3266 ldap_memfree(srv_dn_utf8);
3267 return WERR_SERVER_UNAVAILABLE;
3269 /* Now convert to CH_UNIX. */
3270 if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3272 ldap_memfree(srv_dn_utf8);
3273 ldap_memfree(srv_cn_utf8);
3274 return WERR_SERVER_UNAVAILABLE;
3276 if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3278 ldap_memfree(srv_dn_utf8);
3279 ldap_memfree(srv_cn_utf8);
3280 TALLOC_FREE(srv_dn);
3281 return WERR_SERVER_UNAVAILABLE;
3284 ldap_memfree(srv_dn_utf8);
3285 ldap_memfree(srv_cn_utf8);
3287 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3288 if (!srv_cn_escaped) {
3290 return WERR_SERVER_UNAVAILABLE;
3292 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3293 if (!sharename_escaped) {
3294 SAFE_FREE(srv_cn_escaped);
3296 return WERR_SERVER_UNAVAILABLE;
3299 prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3301 SAFE_FREE(srv_cn_escaped);
3302 SAFE_FREE(sharename_escaped);
3304 mods = ads_init_mods(ctx);
3312 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3313 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3314 printer->info_2->sharename);
3317 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3318 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3320 for (i=0; mods[i] != 0; i++)
3322 mods[i] = (LDAPMod *)-1;
3323 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3326 if (!ADS_ERR_OK(ads_rc))
3327 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3329 /* retreive the guid and store it locally */
3330 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3332 ads_pull_guid(ads, res, &guid);
3333 ads_msgfree(ads, res);
3334 store_printer_guid(printer->info_2, guid);
3335 win_rc = mod_a_printer(printer, 2);
3342 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3343 NT_PRINTER_INFO_LEVEL *printer)
3346 LDAPMessage *res = NULL;
3347 char *prt_dn = NULL;
3349 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3351 /* remove the printer from the directory */
3352 ads_rc = ads_find_printer_on_server(ads, &res,
3353 printer->info_2->sharename, global_myname());
3355 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3356 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3358 ads_msgfree(ads, res);
3361 ads_rc = ads_del_dn(ads, prt_dn);
3362 TALLOC_FREE(prt_dn);
3366 ads_msgfree(ads, res);
3371 /****************************************************************************
3372 * Publish a printer in the directory
3374 * @param snum describing printer service
3375 * @return WERROR indicating status of publishing
3376 ***************************************************************************/
3378 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3381 ADS_STRUCT *ads = NULL;
3382 NT_PRINTER_INFO_LEVEL *printer = NULL;
3385 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3386 if (!W_ERROR_IS_OK(win_rc))
3390 case DSPRINT_PUBLISH:
3391 case DSPRINT_UPDATE:
3392 /* set the DsSpooler info and attributes */
3393 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3394 win_rc = WERR_NOMEM;
3398 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3400 case DSPRINT_UNPUBLISH:
3401 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3404 win_rc = WERR_NOT_SUPPORTED;
3408 win_rc = mod_a_printer(printer, 2);
3409 if (!W_ERROR_IS_OK(win_rc)) {
3410 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3414 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3416 DEBUG(3, ("ads_init() failed\n"));
3417 win_rc = WERR_SERVER_UNAVAILABLE;
3420 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3421 SAFE_FREE(ads->auth.password);
3422 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3425 /* ads_connect() will find the DC for us */
3426 ads_rc = ads_connect(ads);
3427 if (!ADS_ERR_OK(ads_rc)) {
3428 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3429 win_rc = WERR_ACCESS_DENIED;
3434 case DSPRINT_PUBLISH:
3435 case DSPRINT_UPDATE:
3436 win_rc = nt_printer_publish_ads(ads, printer);
3438 case DSPRINT_UNPUBLISH:
3439 win_rc = nt_printer_unpublish_ads(ads, printer);
3444 free_a_printer(&printer, 2);
3449 WERROR check_published_printers(void)
3452 ADS_STRUCT *ads = NULL;
3454 int n_services = lp_numservices();
3455 NT_PRINTER_INFO_LEVEL *printer = NULL;
3457 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3459 DEBUG(3, ("ads_init() failed\n"));
3460 return WERR_SERVER_UNAVAILABLE;
3462 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3463 SAFE_FREE(ads->auth.password);
3464 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3467 /* ads_connect() will find the DC for us */
3468 ads_rc = ads_connect(ads);
3469 if (!ADS_ERR_OK(ads_rc)) {
3470 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3472 ads_kdestroy("MEMORY:prtpub_cache");
3473 return WERR_ACCESS_DENIED;
3476 for (snum = 0; snum < n_services; snum++) {
3477 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3480 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3481 lp_servicename(snum))) &&
3482 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3483 nt_printer_publish_ads(ads, printer);
3485 free_a_printer(&printer, 2);
3489 ads_kdestroy("MEMORY:prtpub_cache");
3493 bool is_printer_published(Printer_entry *print_hnd, int snum,
3496 NT_PRINTER_INFO_LEVEL *printer = NULL;
3497 struct regval_ctr *ctr;
3498 struct regval_blob *guid_val;
3504 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3506 if (!W_ERROR_IS_OK(win_rc) ||
3507 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3508 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3509 !(ctr = printer->info_2->data->keys[i].values) ||
3510 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3512 free_a_printer(&printer, 2);
3516 /* fetching printer guids really ought to be a separate function. */
3521 /* We used to store the guid as REG_BINARY, then swapped
3522 to REG_SZ for Vista compatibility so check for both */
3524 switch ( regval_type(guid_val) ){
3526 blob = data_blob_const(regval_data_p(guid_val),
3527 regval_size(guid_val));
3528 pull_reg_sz(talloc_tos(), &blob, (const char **)&guid_str);
3529 ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3530 talloc_free(guid_str);
3533 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3537 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3540 DEBUG(0,("is_printer_published: GUID value stored as "
3541 "invaluid type (%d)\n", regval_type(guid_val) ));
3546 free_a_printer(&printer, 2);
3550 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3555 WERROR check_published_printers(void)
3560 bool is_printer_published(Printer_entry *print_hnd, int snum,
3565 #endif /* HAVE_ADS */
3567 /****************************************************************************
3568 ***************************************************************************/
3570 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3572 NT_PRINTER_DATA *data;
3574 int removed_keys = 0;
3578 empty_slot = data->num_keys;
3581 return WERR_INVALID_PARAM;
3583 /* remove all keys */
3585 if ( !strlen(key) ) {
3587 TALLOC_FREE( data );
3591 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3597 /* remove a specific key (and all subkeys) */
3599 for ( i=0; i<data->num_keys; i++ ) {
3600 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3601 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3602 data->keys[i].name));
3604 TALLOC_FREE( data->keys[i].name );
3605 TALLOC_FREE( data->keys[i].values );
3607 /* mark the slot as empty */
3609 ZERO_STRUCTP( &data->keys[i] );
3613 /* find the first empty slot */
3615 for ( i=0; i<data->num_keys; i++ ) {
3616 if ( !data->keys[i].name ) {
3623 if ( i == data->num_keys )
3624 /* nothing was removed */
3625 return WERR_INVALID_PARAM;
3627 /* move everything down */
3629 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3630 if ( data->keys[i].name ) {
3631 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3632 ZERO_STRUCTP( &data->keys[i] );
3640 data->num_keys -= removed_keys;
3642 /* sanity check to see if anything is left */
3644 if ( !data->num_keys ) {
3645 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3647 SAFE_FREE( data->keys );
3648 ZERO_STRUCTP( data );
3654 /****************************************************************************
3655 ***************************************************************************/
3657 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3659 WERROR result = WERR_OK;
3662 /* we must have names on non-zero length */
3664 if ( !key || !*key|| !value || !*value )
3665 return WERR_INVALID_NAME;
3667 /* find the printer key first */
3669 key_index = lookup_printerkey( p2->data, key );
3670 if ( key_index == -1 )
3673 /* make sure the value exists so we can return the correct error code */
3675 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3676 return WERR_BADFILE;
3678 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3680 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3686 /****************************************************************************
3687 ***************************************************************************/
3689 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3690 uint32 type, uint8 *data, int real_len )
3692 WERROR result = WERR_OK;
3695 /* we must have names on non-zero length */
3697 if ( !key || !*key|| !value || !*value )
3698 return WERR_INVALID_NAME;
3700 /* find the printer key first */
3702 key_index = lookup_printerkey( p2->data, key );
3703 if ( key_index == -1 )
3704 key_index = add_new_printer_key( p2->data, key );
3706 if ( key_index == -1 )
3709 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3710 type, data, real_len );
3712 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3713 key, value, type, real_len ));
3718 /****************************************************************************
3719 ***************************************************************************/
3721 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3725 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3728 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3731 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3734 /****************************************************************************
3735 Unpack a list of registry values frem the TDB
3736 ***************************************************************************/
3738 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3743 const char *valuename = NULL;
3744 const char *keyname = NULL;
3748 struct regval_blob *regval_p;
3751 /* add the "PrinterDriverData" key first for performance reasons */
3753 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3755 /* loop and unpack the rest of the registry values */
3759 /* check to see if there are any more registry values */
3762 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3766 /* unpack the next regval */
3768 len += tdb_unpack(buf+len, buflen-len, "fdB",
3774 /* lookup for subkey names which have a type of REG_NONE */
3775 /* there's no data with this entry */
3777 if ( type == REG_NONE ) {
3778 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3779 add_new_printer_key( printer_data, string );
3784 * break of the keyname from the value name.
3785 * Valuenames can have embedded '\'s so be careful.
3786 * only support one level of keys. See the
3787 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3791 str = strchr_m( string, '\\');
3793 /* Put in "PrinterDriverData" is no key specified */
3796 keyname = SPOOL_PRINTERDATA_KEY;
3805 /* see if we need a new key */
3807 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3808 key_index = add_new_printer_key( printer_data, keyname );
3810 if ( key_index == -1 ) {
3811 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3816 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3818 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3819 Thanks to Martin Zielinski for the hint. */
3821 if ( type == REG_BINARY &&
3822 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3823 strequal( valuename, "objectGUID" ) )
3827 /* convert the GUID to a UNICODE string */
3829 memcpy( &guid, data_p, sizeof(struct GUID) );
3831 regval_ctr_addvalue_sz(printer_data->keys[key_index].values,
3833 GUID_string(talloc_tos(), &guid));
3838 regval_ctr_addvalue( printer_data->keys[key_index].values,
3839 valuename, type, data_p,
3843 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3850 /****************************************************************************
3851 ***************************************************************************/
3853 static char *win_driver;
3854 static char *os2_driver;
3856 static const char *get_win_driver(void)
3858 if (win_driver == NULL) {
3864 static const char *get_os2_driver(void)
3866 if (os2_driver == NULL) {
3872 static bool set_driver_mapping(const char *from, const char *to)
3874 SAFE_FREE(win_driver);
3875 SAFE_FREE(os2_driver);
3877 win_driver = SMB_STRDUP(from);
3878 os2_driver = SMB_STRDUP(to);
3880 if (win_driver == NULL || os2_driver == NULL) {
3881 SAFE_FREE(win_driver);
3882 SAFE_FREE(os2_driver);
3888 static void map_to_os2_driver(fstring drivername)
3890 char *mapfile = lp_os2_driver_map();
3891 char **lines = NULL;
3895 if (!strlen(drivername))
3901 if (strequal(drivername, get_win_driver())) {
3902 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3903 drivername, get_os2_driver()));
3904 fstrcpy(drivername, get_os2_driver());
3908 lines = file_lines_load(mapfile, &numlines,0,NULL);
3909 if (numlines == 0 || lines == NULL) {
3910 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3915 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3917 for( i = 0; i < numlines; i++) {
3918 char *nt_name = lines[i];
3919 char *os2_name = strchr(nt_name,'=');
3926 while (isspace(*nt_name))
3929 if (!*nt_name || strchr("#;",*nt_name))
3933 int l = strlen(nt_name);
3934 while (l && isspace(nt_name[l-1])) {
3940 while (isspace(*os2_name))
3944 int l = strlen(os2_name);
3945 while (l && isspace(os2_name[l-1])) {
3951 if (strequal(nt_name,drivername)) {
3952 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3953 set_driver_mapping(drivername,os2_name);
3954 fstrcpy(drivername,os2_name);
3966 * @brief Map a Windows driver to a OS/2 driver.
3968 * @param[in] mem_ctx The memory context to use.
3970 * @param[in,out] pdrivername The drivername of Windows to remap.
3972 * @return WERR_OK on success, a corresponding WERROR on failure.
3974 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
3976 const char *mapfile = lp_os2_driver_map();
3977 char **lines = NULL;
3978 const char *drivername;
3982 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
3983 return WERR_INVALID_PARAMETER;
3986 drivername = *pdrivername;
3988 if (mapfile[0] == '\0') {
3989 return WERR_BADFILE;
3992 if (strequal(drivername, get_win_driver())) {
3993 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3994 drivername, get_os2_driver()));
3995 drivername = talloc_strdup(mem_ctx, get_os2_driver());
3996 if (drivername == NULL) {
3999 *pdrivername = drivername;
4003 lines = file_lines_load(mapfile, &numlines, 0, NULL);
4004 if (numlines == 0 || lines == NULL) {
4005 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
4010 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
4012 for( i = 0; i < numlines; i++) {
4013 char *nt_name = lines[i];
4014 char *os2_name = strchr(nt_name, '=');
4016 if (os2_name == NULL) {
4022 while (isspace(*nt_name)) {
4026 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
4031 int l = strlen(nt_name);
4032 while (l && isspace(nt_name[l - 1])) {
4038 while (isspace(*os2_name)) {
4043 int l = strlen(os2_name);
4044 while (l && isspace(os2_name[l-1])) {
4050 if (strequal(nt_name, drivername)) {
4051 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
4052 set_driver_mapping(drivername, os2_name);
4053 drivername = talloc_strdup(mem_ctx, os2_name);
4055 if (drivername == NULL) {
4058 *pdrivername = drivername;
4067 /****************************************************************************
4068 Get a default printer info 2 struct.
4069 ****************************************************************************/
4071 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
4072 const char *servername,
4073 const char* sharename,
4076 int snum = lp_servicenumber(sharename);
4078 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4079 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4080 servername, sharename);
4081 fstrcpy(info->sharename, sharename);
4082 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
4084 /* by setting the driver name to an empty string, a local NT admin
4085 can now run the **local** APW to install a local printer driver
4086 for a Samba shared printer in 2.2. Without this, drivers **must** be
4087 installed on the Samba server for NT clients --jerry */
4088 #if 0 /* JERRY --do not uncomment-- */
4089 if (!*info->drivername)
4090 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
4094 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
4096 strlcpy(info->comment, "", sizeof(info->comment));
4097 fstrcpy(info->printprocessor, "winprint");
4098 fstrcpy(info->datatype, "RAW");
4101 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4102 /* Pull the location and comment strings from cups if we don't
4104 if ( !strlen(info->location) || !strlen(info->comment) ) {
4105 char *comment = NULL;
4106 char *location = NULL;
4107 if (cups_pull_comment_location(info, info->sharename,
4108 &comment, &location)) {
4109 strlcpy(info->comment, comment, sizeof(info->comment));
4110 fstrcpy(info->location, location);
4111 TALLOC_FREE(comment);
4112 TALLOC_FREE(location);
4118 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
4120 info->starttime = 0; /* Minutes since 12:00am GMT */
4121 info->untiltime = 0; /* Minutes since 12:00am GMT */
4123 info->default_priority = 1;
4124 info->setuptime = (uint32)time(NULL);
4127 * I changed this as I think it is better to have a generic
4128 * DEVMODE than to crash Win2k explorer.exe --jerry
4129 * See the HP Deskjet 990c Win2k drivers for an example.
4131 * However the default devmode appears to cause problems
4132 * with the HP CLJ 8500 PCL driver. Hence the addition of
4133 * the "default devmode" parameter --jerry 22/01/2002
4136 if (lp_default_devmode(snum)) {
4137 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
4141 info->devmode = NULL;
4144 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4148 info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
4153 add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
4159 free_nt_devicemode(&info->devmode);
4161 return WERR_ACCESS_DENIED;
4164 /****************************************************************************
4165 ****************************************************************************/
4167 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
4168 const char *servername,
4169 const char *sharename,
4173 int snum = lp_servicenumber(sharename);
4174 TDB_DATA kbuf, dbuf;
4175 fstring printername;
4176 char adevice[MAXDEVICENAME];
4177 char *comment = NULL;
4179 kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4181 dbuf = tdb_fetch(tdb_printers, kbuf);
4183 return get_a_printer_2_default(info, servername,
4184 sharename, get_loc_com);
4187 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4190 &info->default_priority,
4197 &info->c_setprinter,
4207 info->printprocessor,
4212 strlcpy(info->comment, comment, sizeof(info->comment));
4216 /* Samba has to have shared raw drivers. */
4217 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4218 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4220 /* Restore the stripped strings. */
4221 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4223 if ( lp_force_printername(snum) ) {
4224 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4226 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4229 fstrcpy(info->printername, printername);
4232 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4233 /* Pull the location and comment strings from cups if we don't
4235 if ( !strlen(info->location) || !strlen(info->comment) ) {
4236 char *location = NULL;
4238 if (cups_pull_comment_location(info, info->sharename,
4239 &comment, &location)) {
4240 strlcpy(info->comment, comment, sizeof(info->comment));
4241 fstrcpy(info->location, location);
4242 TALLOC_FREE(comment);
4243 TALLOC_FREE(location);
4249 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4252 * Some client drivers freak out if there is a NULL devmode
4253 * (probably the driver is not checking before accessing
4254 * the devmode pointer) --jerry
4256 * See comments in get_a_printer_2_default()
4259 if (lp_default_devmode(snum) && !info->devmode) {
4260 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4262 info->devmode = construct_nt_devicemode(printername);
4265 slprintf( adevice, sizeof(adevice), "%s", info->printername );
4266 if (info->devmode) {
4267 fstrcpy(info->devmode->devicename, adevice);
4270 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4271 DEBUG(0,("unpack_values: talloc() failed!\n"));
4272 SAFE_FREE(dbuf.dptr);
4275 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4277 /* This will get the current RPC talloc context, but we should be
4278 passing this as a parameter... fixme... JRA ! */
4280 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4281 SAFE_FREE(dbuf.dptr);
4285 /* Fix for OS/2 drivers. */
4287 if (get_remote_arch() == RA_OS2) {
4288 map_to_os2_driver(info->drivername);
4291 SAFE_FREE(dbuf.dptr);
4293 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4294 sharename, info->printername, info->drivername));
4299 /****************************************************************************
4300 Debugging function, dump at level 6 the struct in the logs.
4301 ****************************************************************************/
4302 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4305 NT_PRINTER_INFO_LEVEL_2 *info2;
4307 DEBUG(106,("Dumping printer at level [%d]\n", level));
4312 if (printer->info_2 == NULL)
4316 info2=printer->info_2;
4318 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4319 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4320 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4321 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4322 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4323 DEBUGADD(106,("status:[%d]\n", info2->status));
4324 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4325 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4326 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4327 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4328 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4330 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4331 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4332 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4333 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4334 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4335 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4336 DEBUGADD(106,("location:[%s]\n", info2->location));
4337 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4338 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4339 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4340 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4346 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4354 /****************************************************************************
4355 Update the changeid time.
4356 This is SO NASTY as some drivers need this to change, others need it
4357 static. This value will change every second, and I must hope that this
4358 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4360 ****************************************************************************/
4362 static uint32 rev_changeid(void)
4366 get_process_uptime(&tv);
4369 /* Return changeid as msec since spooler restart */
4370 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4373 * This setting seems to work well but is too untested
4374 * to replace the above calculation. Left in for experiementation
4375 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4377 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4383 * The function below are the high level ones.
4384 * only those ones must be called from the spoolss code.
4388 /****************************************************************************
4389 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4390 ****************************************************************************/
4392 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4396 dump_a_printer(printer, level);
4402 * Update the changestamp. Emperical tests show that the
4403 * ChangeID is always updated,but c_setprinter is
4404 * global spooler variable (not per printer).
4407 /* ChangeID **must** be increasing over the lifetime
4408 of client's spoolss service in order for the
4409 client's cache to show updates */
4411 printer->info_2->changeid = rev_changeid();
4414 * Because one day someone will ask:
4415 * NT->NT An admin connection to a remote
4416 * printer show changes imeediately in
4417 * the properities dialog
4419 * A non-admin connection will only show the
4420 * changes after viewing the properites page
4421 * 2 times. Seems to be related to a
4422 * race condition in the client between the spooler
4423 * updating the local cache and the Explorer.exe GUI
4424 * actually displaying the properties.
4426 * This is fixed in Win2k. admin/non-admin
4427 * connections both display changes immediately.
4432 result=update_a_printer_2(printer->info_2);
4436 result=WERR_UNKNOWN_LEVEL;
4443 /****************************************************************************
4444 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4446 Previously the code had a memory allocation problem because it always
4447 used the TALLOC_CTX from the Printer_entry*. This context lasts
4448 as a long as the original handle is open. So if the client made a lot
4449 of getprinter[data]() calls, the memory usage would climb. Now we use
4450 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4451 still use the Printer_entry->ctx for maintaining the cache copy though
4452 since that object must live as long as the handle by definition.
4455 ****************************************************************************/
4457 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4458 const char *sharename, bool get_loc_com)
4463 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4465 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4466 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4472 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4473 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4474 TALLOC_FREE( *pp_printer );
4479 fstrcpy( servername, print_hnd->servername );
4481 fstrcpy( servername, "%L" );
4482 standard_sub_basic( "", "", servername,
4483 sizeof(servername)-1 );
4486 result = get_a_printer_2( (*pp_printer)->info_2,
4487 servername, sharename, get_loc_com);
4489 /* we have a new printer now. Save it with this handle */
4491 if ( !W_ERROR_IS_OK(result) ) {
4492 TALLOC_FREE( *pp_printer );
4493 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4494 sharename, (unsigned int)level, win_errstr(result)));
4498 dump_a_printer( *pp_printer, level);
4503 TALLOC_FREE( *pp_printer );
4504 return WERR_UNKNOWN_LEVEL;
4510 WERROR get_a_printer( Printer_entry *print_hnd,
4511 NT_PRINTER_INFO_LEVEL **pp_printer,
4513 const char *sharename)
4515 return get_a_printer_internal(print_hnd, pp_printer, level,
4519 WERROR get_a_printer_search( Printer_entry *print_hnd,
4520 NT_PRINTER_INFO_LEVEL **pp_printer,
4522 const char *sharename)
4524 return get_a_printer_internal(print_hnd, pp_printer, level,
4528 /****************************************************************************
4529 Deletes a NT_PRINTER_INFO_LEVEL struct.
4530 ****************************************************************************/
4532 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4534 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4541 if ( printer->info_2 )
4542 free_nt_printer_info_level_2(&printer->info_2);
4546 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4550 TALLOC_FREE(*pp_printer);
4555 /****************************************************************************
4556 ****************************************************************************/
4558 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
4559 struct spoolss_DriverInfo8 *_info8)
4561 struct spoolss_DriverInfo8 info8;
4567 info8.version = r->info.info3->version;
4568 info8.driver_name = r->info.info3->driver_name;
4569 info8.architecture = r->info.info3->architecture;
4570 info8.driver_path = r->info.info3->driver_path;
4571 info8.data_file = r->info.info3->data_file;
4572 info8.config_file = r->info.info3->config_file;
4573 info8.help_file = r->info.info3->help_file;
4574 info8.monitor_name = r->info.info3->monitor_name;
4575 info8.default_datatype = r->info.info3->default_datatype;
4576 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
4577 info8.dependent_files = r->info.info3->dependent_files->string;
4581 info8.version = r->info.info6->version;
4582 info8.driver_name = r->info.info6->driver_name;
4583 info8.architecture = r->info.info6->architecture;
4584 info8.driver_path = r->info.info6->driver_path;
4585 info8.data_file = r->info.info6->data_file;
4586 info8.config_file = r->info.info6->config_file;
4587 info8.help_file = r->info.info6->help_file;
4588 info8.monitor_name = r->info.info6->monitor_name;
4589 info8.default_datatype = r->info.info6->default_datatype;
4590 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
4591 info8.dependent_files = r->info.info6->dependent_files->string;
4593 info8.driver_date = r->info.info6->driver_date;
4594 info8.driver_version = r->info.info6->driver_version;
4595 info8.manufacturer_name = r->info.info6->manufacturer_name;
4596 info8.manufacturer_url = r->info.info6->manufacturer_url;
4597 info8.hardware_id = r->info.info6->hardware_id;
4598 info8.provider = r->info.info6->provider;
4601 info8.version = r->info.info8->version;
4602 info8.driver_name = r->info.info8->driver_name;
4603 info8.architecture = r->info.info8->architecture;
4604 info8.driver_path = r->info.info8->driver_path;
4605 info8.data_file = r->info.info8->data_file;
4606 info8.config_file = r->info.info8->config_file;
4607 info8.help_file = r->info.info8->help_file;
4608 info8.monitor_name = r->info.info8->monitor_name;
4609 info8.default_datatype = r->info.info8->default_datatype;
4610 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
4611 info8.dependent_files = r->info.info8->dependent_files->string;
4613 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
4614 info8.previous_names = r->info.info8->previous_names->string;
4616 info8.driver_date = r->info.info8->driver_date;
4617 info8.driver_version = r->info.info8->driver_version;
4618 info8.manufacturer_name = r->info.info8->manufacturer_name;
4619 info8.manufacturer_url = r->info.info8->manufacturer_url;
4620 info8.hardware_id = r->info.info8->hardware_id;
4621 info8.provider = r->info.info8->provider;
4622 info8.print_processor = r->info.info8->print_processor;
4623 info8.vendor_setup = r->info.info8->vendor_setup;
4624 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
4625 info8.color_profiles = r->info.info8->color_profiles->string;
4627 info8.inf_path = r->info.info8->inf_path;
4628 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
4629 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
4630 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
4632 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
4633 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
4645 uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx,
4646 struct spoolss_AddDriverInfoCtr *r,
4650 struct spoolss_DriverInfo8 info8;
4654 DEBUG(10,("adding a printer at level [%d]\n", r->level));
4656 if (!driver_info_ctr_to_info8(r, &info8)) {
4660 *driver_name = talloc_strdup(mem_ctx, info8.driver_name);
4661 if (!*driver_name) {
4664 *version = info8.version;
4666 return add_a_printer_driver_8(&info8);
4669 /****************************************************************************
4670 ****************************************************************************/
4672 WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx,
4673 struct spoolss_DriverInfo8 **driver,
4674 const char *drivername, const char *architecture,
4678 struct spoolss_DriverInfo3 info3;
4679 struct spoolss_DriverInfo8 *info8;
4683 /* Sometime we just want any version of the driver */
4685 if (version == DRIVER_ANY_VERSION) {
4686 /* look for Win2k first and then for NT4 */
4687 result = get_a_printer_driver_3(mem_ctx,
4691 if (!W_ERROR_IS_OK(result)) {
4692 result = get_a_printer_driver_3(mem_ctx,
4698 result = get_a_printer_driver_3(mem_ctx,
4705 if (!W_ERROR_IS_OK(result)) {
4709 info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8);
4714 info8->version = info3.version;
4715 info8->driver_name = info3.driver_name;
4716 info8->architecture = info3.architecture;
4717 info8->driver_path = info3.driver_path;
4718 info8->data_file = info3.data_file;
4719 info8->config_file = info3.config_file;
4720 info8->help_file = info3.help_file;
4721 info8->dependent_files = info3.dependent_files;
4722 info8->monitor_name = info3.monitor_name;
4723 info8->default_datatype = info3.default_datatype;
4730 /****************************************************************************
4731 ****************************************************************************/
4733 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver)
4735 talloc_free(driver);
4740 /****************************************************************************
4741 Determine whether or not a particular driver is currently assigned
4743 ****************************************************************************/
4745 bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r)
4748 int n_services = lp_numservices();
4749 NT_PRINTER_INFO_LEVEL *printer = NULL;
4750 bool in_use = False;
4756 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4758 /* loop through the printers.tdb and check for the drivername */
4760 for (snum=0; snum<n_services && !in_use; snum++) {
4761 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4764 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4767 if (strequal(r->driver_name, printer->info_2->drivername))
4770 free_a_printer( &printer, 2 );
4773 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4776 struct spoolss_DriverInfo8 *d;
4779 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
4781 /* we can still remove the driver if there is one of
4782 "Windows NT x86" version 2 or 3 left */
4784 if (!strequal("Windows NT x86", r->architecture)) {
4785 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION);
4788 switch (r->version) {
4790 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3);
4793 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2);
4796 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4798 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4803 /* now check the error code */
4805 if ( W_ERROR_IS_OK(werr) ) {
4806 /* it's ok to remove the driver, we have other architctures left */
4808 free_a_printer_driver(d);
4812 /* report that the driver is not in use by default */
4818 /**********************************************************************
4819 Check to see if a ogiven file is in use by *info
4820 *********************************************************************/
4822 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
4829 /* mz: skip files that are in the list but already deleted */
4830 if (!file || !file[0]) {
4834 if (strequal(file, info->driver_path))
4837 if (strequal(file, info->data_file))
4840 if (strequal(file, info->config_file))
4843 if (strequal(file, info->help_file))
4846 /* see of there are any dependent files to examine */
4848 if (!info->dependent_files)
4851 while (info->dependent_files[i] && *info->dependent_files[i]) {
4852 if (strequal(file, info->dependent_files[i]))
4861 /**********************************************************************
4862 Utility function to remove the dependent file pointed to by the
4863 input parameter from the list
4864 *********************************************************************/
4866 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
4869 /* bump everything down a slot */
4871 while (files && files[idx+1]) {
4872 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
4881 /**********************************************************************
4882 Check if any of the files used by src are also used by drv
4883 *********************************************************************/
4885 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
4886 struct spoolss_DriverInfo8 *src,
4887 const struct spoolss_DriverInfo8 *drv)
4889 bool in_use = False;
4895 /* check each file. Remove it from the src structure if it overlaps */
4897 if (drv_file_in_use(src->driver_path, drv)) {
4899 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
4900 src->driver_path = talloc_strdup(mem_ctx, "");
4901 if (!src->driver_path) { return false; }
4904 if (drv_file_in_use(src->data_file, drv)) {
4906 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
4907 src->data_file = talloc_strdup(mem_ctx, "");
4908 if (!src->data_file) { return false; }
4911 if (drv_file_in_use(src->config_file, drv)) {
4913 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
4914 src->config_file = talloc_strdup(mem_ctx, "");
4915 if (!src->config_file) { return false; }
4918 if (drv_file_in_use(src->help_file, drv)) {
4920 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
4921 src->help_file = talloc_strdup(mem_ctx, "");
4922 if (!src->help_file) { return false; }
4925 /* are there any dependentfiles to examine? */
4927 if (!src->dependent_files)
4930 while (src->dependent_files[i] && *src->dependent_files[i]) {
4931 if (drv_file_in_use(src->dependent_files[i], drv)) {
4933 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
4934 trim_dependent_file(mem_ctx, src->dependent_files, i);
4942 /****************************************************************************
4943 Determine whether or not a particular driver files are currently being
4944 used by any other driver.
4946 Return value is True if any files were in use by other drivers
4947 and False otherwise.
4949 Upon return, *info has been modified to only contain the driver files
4950 which are not in use
4954 This needs to check all drivers to ensure that all files in use
4955 have been removed from *info, not just the ones in the first
4957 ****************************************************************************/
4959 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
4960 struct spoolss_DriverInfo8 *info)
4965 fstring *list = NULL;
4966 struct spoolss_DriverInfo8 *driver;
4967 bool in_use = false;
4972 version = info->version;
4974 /* loop over all driver versions */
4976 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4978 /* get the list of drivers */
4981 ndrivers = get_ntdrivers(&list, info->architecture, version);
4983 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4984 ndrivers, info->architecture, version));
4986 /* check each driver for overlap in files */
4988 for (i=0; i<ndrivers; i++) {
4989 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4993 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, list[i], info->architecture, version))) {
4998 /* check if d2 uses any files from d1 */
4999 /* only if this is a different driver than the one being deleted */
5001 if (!strequal(info->driver_name, driver->driver_name)) {
5002 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
5003 /* mz: Do not instantly return -
5004 * we need to ensure this file isn't
5005 * also in use by other drivers. */
5010 free_a_printer_driver(driver);
5015 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5020 static NTSTATUS driver_unlink_internals(connection_struct *conn,
5023 struct smb_filename *smb_fname = NULL;
5026 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
5028 if (!NT_STATUS_IS_OK(status)) {
5032 status = unlink_internals(conn, NULL, 0, smb_fname, false);
5034 TALLOC_FREE(smb_fname);
5038 /****************************************************************************
5039 Actually delete the driver files. Make sure that
5040 printer_driver_files_in_use() return False before calling
5042 ****************************************************************************/
5044 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
5045 const struct spoolss_DriverInfo8 *r)
5050 connection_struct *conn;
5053 fstring printdollar;
5054 int printdollar_snum;
5061 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
5062 r->driver_name, r->version));
5064 fstrcpy(printdollar, "print$");
5066 printdollar_snum = find_service(printdollar);
5067 if (printdollar_snum == -1) {
5071 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5072 lp_pathname(printdollar_snum),
5073 rpc_pipe->server_info, &oldcwd);
5074 if (!NT_STATUS_IS_OK(nt_status)) {
5075 DEBUG(0,("delete_driver_files: create_conn_struct "
5076 "returned %s\n", nt_errstr(nt_status)));
5080 if ( !CAN_WRITE(conn) ) {
5081 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5085 /* now delete the files; must strip the '\print$' string from
5088 if (r->driver_path && r->driver_path[0]) {
5089 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
5091 DEBUG(10,("deleting driverfile [%s]\n", s));
5092 driver_unlink_internals(conn, file);
5096 if (r->config_file && r->config_file[0]) {
5097 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
5099 DEBUG(10,("deleting configfile [%s]\n", s));
5100 driver_unlink_internals(conn, file);
5104 if (r->data_file && r->data_file[0]) {
5105 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
5107 DEBUG(10,("deleting datafile [%s]\n", s));
5108 driver_unlink_internals(conn, file);
5112 if (r->help_file && r->help_file[0]) {
5113 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
5115 DEBUG(10,("deleting helpfile [%s]\n", s));
5116 driver_unlink_internals(conn, file);
5120 /* check if we are done removing files */
5122 if (r->dependent_files) {
5123 while (r->dependent_files[i] && r->dependent_files[i][0]) {
5126 /* bypass the "\print$" portion of the path */
5128 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
5130 DEBUG(10,("deleting dependent file [%s]\n", file));
5131 driver_unlink_internals(conn, file);
5143 vfs_ChDir(conn, oldcwd);
5149 /****************************************************************************
5150 Remove a printer driver from the TDB. This assumes that the the driver was
5151 previously looked up.
5152 ***************************************************************************/
5154 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5155 const struct spoolss_DriverInfo8 *r,
5156 uint32 version, bool delete_files )
5162 /* delete the tdb data first */
5164 arch = get_short_archi(r->architecture);
5166 return WERR_UNKNOWN_PRINTER_DRIVER;
5168 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5169 arch, version, r->driver_name) < 0) {
5173 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5174 key, delete_files ? "TRUE" : "FALSE" ));
5176 /* check if the driver actually exists for this environment */
5178 dbuf = tdb_fetch_bystring( tdb_drivers, key );
5180 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5182 return WERR_UNKNOWN_PRINTER_DRIVER;
5185 SAFE_FREE( dbuf.dptr );
5187 /* ok... the driver exists so the delete should return success */
5189 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5190 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5192 return WERR_ACCESS_DENIED;
5196 * now delete any associated files if delete_files == True
5197 * even if this part failes, we return succes because the
5198 * driver doesn not exist any more
5202 delete_driver_files(rpc_pipe, r);
5204 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5210 /****************************************************************************
5211 Store a security desc for a printer.
5212 ****************************************************************************/
5214 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
5216 struct sec_desc_buf *new_secdesc_ctr = NULL;
5217 struct sec_desc_buf *old_secdesc_ctr = NULL;
5218 TALLOC_CTX *mem_ctx = NULL;
5225 mem_ctx = talloc_init("nt_printing_setsec");
5226 if (mem_ctx == NULL)
5229 /* The old owner and group sids of the security descriptor are not
5230 present when new ACEs are added or removed by changing printer
5231 permissions through NT. If they are NULL in the new security
5232 descriptor then copy them over from the old one. */
5234 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5235 struct dom_sid *owner_sid, *group_sid;
5236 struct security_acl *dacl, *sacl;
5237 struct security_descriptor *psd = NULL;
5240 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5241 status = WERR_NOMEM;
5245 /* Pick out correct owner and group sids */
5247 owner_sid = secdesc_ctr->sd->owner_sid ?
5248 secdesc_ctr->sd->owner_sid :
5249 old_secdesc_ctr->sd->owner_sid;
5251 group_sid = secdesc_ctr->sd->group_sid ?
5252 secdesc_ctr->sd->group_sid :
5253 old_secdesc_ctr->sd->group_sid;
5255 dacl = secdesc_ctr->sd->dacl ?
5256 secdesc_ctr->sd->dacl :
5257 old_secdesc_ctr->sd->dacl;
5259 sacl = secdesc_ctr->sd->sacl ?
5260 secdesc_ctr->sd->sacl :
5261 old_secdesc_ctr->sd->sacl;
5263 /* Make a deep copy of the security descriptor */
5265 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5266 owner_sid, group_sid,
5272 status = WERR_NOMEM;
5276 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5279 if (!new_secdesc_ctr) {
5280 new_secdesc_ctr = secdesc_ctr;
5283 /* Store the security descriptor in a tdb */
5285 nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5286 &blob.data, &blob.length);
5287 if (!NT_STATUS_IS_OK(nt_status)) {
5288 status = ntstatus_to_werror(nt_status);
5292 kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5294 dbuf.dptr = (unsigned char *)blob.data;
5295 dbuf.dsize = blob.length;
5297 if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5300 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5301 status = WERR_BADFUNC;
5304 /* Free malloc'ed memory */
5305 talloc_free(blob.data);
5310 talloc_destroy(mem_ctx);
5314 /****************************************************************************
5315 Construct a default security descriptor buffer for a printer.
5316 ****************************************************************************/
5318 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
5320 struct security_ace ace[5]; /* max number of ace entries */
5323 struct security_acl *psa = NULL;
5324 struct sec_desc_buf *sdb = NULL;
5325 struct security_descriptor *psd = NULL;
5326 struct dom_sid adm_sid;
5329 /* Create an ACE where Everyone is allowed to print */
5331 sa = PRINTER_ACE_PRINT;
5332 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5333 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5335 /* Add the domain admins group if we are a DC */
5338 struct dom_sid domadmins_sid;
5340 sid_compose(&domadmins_sid, get_global_sam_sid(),
5343 sa = PRINTER_ACE_FULL_CONTROL;
5344 init_sec_ace(&ace[i++], &domadmins_sid,
5345 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5346 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5347 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5348 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5350 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5351 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
5353 sa = PRINTER_ACE_FULL_CONTROL;
5354 init_sec_ace(&ace[i++], &adm_sid,
5355 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5356 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5357 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5358 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5361 /* add BUILTIN\Administrators as FULL CONTROL */
5363 sa = PRINTER_ACE_FULL_CONTROL;
5364 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5365 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5366 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5367 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5368 SEC_ACE_TYPE_ACCESS_ALLOWED,
5369 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5371 /* Make the security descriptor owned by the BUILTIN\Administrators */
5373 /* The ACL revision number in rpc_secdesc.h differs from the one
5374 created by NT when setting ACE entries in printer
5375 descriptors. NT4 complains about the property being edited by a
5378 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5379 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
5380 &global_sid_Builtin_Administrators,
5381 &global_sid_Builtin_Administrators,
5382 NULL, psa, &sd_size);
5386 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5390 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5392 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5393 (unsigned int)sd_size));
5398 /****************************************************************************
5399 Get a security desc for a printer.
5400 ****************************************************************************/
5402 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
5410 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5411 sharename = temp + 1;
5414 /* Fetch security descriptor from tdb */
5416 kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5418 dbuf = tdb_fetch(tdb_printers, kbuf);
5421 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5423 SAFE_FREE(dbuf.dptr);
5425 if (NT_STATUS_IS_OK(status)) {
5430 *secdesc_ctr = construct_default_printer_sdb(ctx);
5431 if (!*secdesc_ctr) {
5435 status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5436 &blob.data, &blob.length);
5437 if (NT_STATUS_IS_OK(status)) {
5438 dbuf.dptr = (unsigned char *)blob.data;
5439 dbuf.dsize = blob.length;
5440 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5441 talloc_free(blob.data);
5444 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5445 this security descriptor has been created when winbindd was
5446 down. Take ownership of security descriptor. */
5448 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5449 struct dom_sid owner_sid;
5451 /* Change sd owner to workgroup administrator */
5453 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5454 struct sec_desc_buf *new_secdesc_ctr = NULL;
5455 struct security_descriptor *psd = NULL;
5460 sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
5462 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5464 (*secdesc_ctr)->sd->group_sid,
5465 (*secdesc_ctr)->sd->sacl,
5466 (*secdesc_ctr)->sd->dacl,
5473 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5474 if (!new_secdesc_ctr) {
5478 /* Swap with other one */
5480 *secdesc_ctr = new_secdesc_ctr;
5484 nt_printing_setsec(sharename, *secdesc_ctr);
5488 if (DEBUGLEVEL >= 10) {
5489 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
5492 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5493 sharename, the_acl->num_aces));
5495 for (i = 0; i < the_acl->num_aces; i++) {
5496 DEBUG(10, ("%s %d %d 0x%08x\n",
5497 sid_string_dbg(&the_acl->aces[i].trustee),
5498 the_acl->aces[i].type, the_acl->aces[i].flags,
5499 the_acl->aces[i].access_mask));
5508 1: level not implemented
5509 2: file doesn't exist
5510 3: can't allocate memory
5511 4: can't free memory
5512 5: non existant struct
5516 A printer and a printer driver are 2 different things.
5517 NT manages them separatelly, Samba does the same.
5518 Why ? Simply because it's easier and it makes sense !
5520 Now explanation: You have 3 printers behind your samba server,
5521 2 of them are the same make and model (laser A and B). But laser B
5522 has an 3000 sheet feeder and laser A doesn't such an option.
5523 Your third printer is an old dot-matrix model for the accounting :-).
5525 If the /usr/local/samba/lib directory (default dir), you will have
5526 5 files to describe all of this.
5528 3 files for the printers (1 by printer):
5531 NTprinter_accounting
5532 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5533 NTdriver_printer model X
5534 NTdriver_printer model Y
5536 jfm: I should use this comment for the text file to explain
5537 same thing for the forms BTW.
5538 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5542 /* Convert generic access rights to printer object specific access rights.
5543 It turns out that NT4 security descriptors use generic access rights and
5544 NT5 the object specific ones. */
5546 void map_printer_permissions(struct security_descriptor *sd)
5550 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5551 se_map_generic(&sd->dacl->aces[i].access_mask,
5552 &printer_generic_mapping);
5556 void map_job_permissions(struct security_descriptor *sd)
5560 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5561 se_map_generic(&sd->dacl->aces[i].access_mask,
5562 &job_generic_mapping);
5567 /****************************************************************************
5568 Check a user has permissions to perform the given operation. We use the
5569 permission constants defined in include/rpc_spoolss.h to check the various
5570 actions we perform when checking printer access.
5572 PRINTER_ACCESS_ADMINISTER:
5573 print_queue_pause, print_queue_resume, update_printer_sec,
5574 update_printer, spoolss_addprinterex_level_2,
5575 _spoolss_setprinterdata
5580 JOB_ACCESS_ADMINISTER:
5581 print_job_delete, print_job_pause, print_job_resume,
5584 Try access control in the following order (for performance reasons):
5585 1) root and SE_PRINT_OPERATOR can do anything (easy check)
5586 2) check security descriptor (bit comparisons in memory)
5587 3) "printer admins" (may result in numerous calls to winbind)
5589 ****************************************************************************/
5590 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5593 struct sec_desc_buf *secdesc = NULL;
5594 uint32 access_granted;
5597 TALLOC_CTX *mem_ctx = NULL;
5598 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5600 /* If user is NULL then use the current_user structure */
5602 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5604 if (server_info->utok.uid == sec_initial_uid()
5605 || user_has_privileges(server_info->ptok, &se_printop ) ) {
5609 /* Get printer name */
5611 pname = lp_printername(snum);
5613 if (!pname || !*pname) {
5618 /* Get printer security descriptor */
5620 if(!(mem_ctx = talloc_init("print_access_check"))) {
5625 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5626 talloc_destroy(mem_ctx);
5631 if (access_type == JOB_ACCESS_ADMINISTER) {
5632 struct sec_desc_buf *parent_secdesc = secdesc;
5634 /* Create a child security descriptor to check permissions
5635 against. This is because print jobs are child objects
5636 objects of a printer. */
5638 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5640 if (!NT_STATUS_IS_OK(status)) {
5641 talloc_destroy(mem_ctx);
5642 errno = map_errno_from_nt_status(status);
5646 map_job_permissions(secdesc->sd);
5648 map_printer_permissions(secdesc->sd);
5652 status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5655 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5657 /* see if we need to try the printer admin list */
5659 if (!NT_STATUS_IS_OK(status) &&
5660 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5661 NULL, NULL, server_info->ptok,
5662 lp_printer_admin(snum)))) {
5663 talloc_destroy(mem_ctx);
5667 talloc_destroy(mem_ctx);
5669 if (!NT_STATUS_IS_OK(status)) {
5673 return NT_STATUS_IS_OK(status);
5676 /****************************************************************************
5677 Check the time parameters allow a print operation.
5678 *****************************************************************************/
5680 bool print_time_access_check(const char *servicename)
5682 NT_PRINTER_INFO_LEVEL *printer = NULL;
5684 time_t now = time(NULL);
5688 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5691 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5695 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5697 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5700 free_a_printer(&printer, 2);
5708 /****************************************************************************
5709 Fill in the servername sent in the _spoolss_open_printer_ex() call
5710 ****************************************************************************/
5712 char* get_server_name( Printer_entry *printer )
5714 return printer->servername;