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[7]; /* 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 /* add BUILTIN\Print Operators as FULL CONTROL */
2685 sa = PRINTER_ACE_FULL_CONTROL;
2686 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2687 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2688 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2689 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2690 SEC_ACE_TYPE_ACCESS_ALLOWED,
2691 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2693 /* Make the security descriptor owned by the BUILTIN\Administrators */
2695 /* The ACL revision number in rpc_secdesc.h differs from the one
2696 created by NT when setting ACE entries in printer
2697 descriptors. NT4 complains about the property being edited by a
2700 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
2701 psd = make_sec_desc(mem_ctx,
2703 SEC_DESC_SELF_RELATIVE,
2704 &global_sid_Builtin_Administrators,
2705 &global_sid_Builtin_Administrators,
2712 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2716 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2717 (unsigned int)sd_size));
2724 /****************************************************************************
2725 Malloc and return an NT devicemode.
2726 ****************************************************************************/
2728 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2731 char adevice[MAXDEVICENAME];
2732 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2734 if (nt_devmode == NULL) {
2735 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2739 ZERO_STRUCTP(nt_devmode);
2741 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2742 fstrcpy(nt_devmode->devicename, adevice);
2744 fstrcpy(nt_devmode->formname, "Letter");
2746 nt_devmode->specversion = DMSPEC_NT4_AND_ABOVE;
2747 nt_devmode->driverversion = 0x0400;
2748 nt_devmode->size = 0x00DC;
2749 nt_devmode->driverextra = 0x0000;
2750 nt_devmode->fields = DEVMODE_FORMNAME |
2752 DEVMODE_PRINTQUALITY |
2753 DEVMODE_DEFAULTSOURCE |
2757 DEVMODE_ORIENTATION;
2758 nt_devmode->orientation = DMORIENT_PORTRAIT;
2759 nt_devmode->papersize = DMPAPER_LETTER;
2760 nt_devmode->paperlength = 0;
2761 nt_devmode->paperwidth = 0;
2762 nt_devmode->scale = 0x64;
2763 nt_devmode->copies = 1;
2764 nt_devmode->defaultsource = DMBIN_FORMSOURCE;
2765 nt_devmode->printquality = DMRES_HIGH; /* 0x0258 */
2766 nt_devmode->color = DMRES_MONOCHROME;
2767 nt_devmode->duplex = DMDUP_SIMPLEX;
2768 nt_devmode->yresolution = 0;
2769 nt_devmode->ttoption = DMTT_SUBDEV;
2770 nt_devmode->collate = DMCOLLATE_FALSE;
2771 nt_devmode->icmmethod = 0;
2772 nt_devmode->icmintent = 0;
2773 nt_devmode->mediatype = 0;
2774 nt_devmode->dithertype = 0;
2776 /* non utilisés par un driver d'imprimante */
2777 nt_devmode->logpixels = 0;
2778 nt_devmode->bitsperpel = 0;
2779 nt_devmode->pelswidth = 0;
2780 nt_devmode->pelsheight = 0;
2781 nt_devmode->displayflags = 0;
2782 nt_devmode->displayfrequency = 0;
2783 nt_devmode->reserved1 = 0;
2784 nt_devmode->reserved2 = 0;
2785 nt_devmode->panningwidth = 0;
2786 nt_devmode->panningheight = 0;
2788 nt_devmode->nt_dev_private = NULL;
2792 /****************************************************************************
2793 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2794 ****************************************************************************/
2796 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2798 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2800 if(nt_devmode == NULL)
2803 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2805 SAFE_FREE(nt_devmode->nt_dev_private);
2806 SAFE_FREE(*devmode_ptr);
2809 /****************************************************************************
2810 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2811 ****************************************************************************/
2813 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2815 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2820 free_nt_devicemode(&info->devmode);
2822 TALLOC_FREE( *info_ptr );
2826 /****************************************************************************
2827 ****************************************************************************/
2828 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2832 NT_DEVICEMODE devmode;
2834 ZERO_STRUCT(devmode);
2836 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2838 if (!*nt_devmode) return len;
2840 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2844 &devmode.specversion,
2845 &devmode.driverversion,
2847 &devmode.driverextra,
2848 &devmode.orientation,
2850 &devmode.paperlength,
2851 &devmode.paperwidth,
2854 &devmode.defaultsource,
2855 &devmode.printquality,
2858 &devmode.yresolution,
2864 &devmode.bitsperpel,
2866 &devmode.pelsheight,
2867 &devmode.displayflags,
2868 &devmode.displayfrequency,
2872 &devmode.dithertype,
2875 &devmode.panningwidth,
2876 &devmode.panningheight,
2877 &devmode.nt_dev_private);
2879 if (devmode.nt_dev_private) {
2880 /* the len in tdb_unpack is an int value and
2881 * devmode.driverextra is only a short
2883 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2884 devmode.driverextra=(uint16)extra_len;
2886 /* check to catch an invalid TDB entry so we don't segfault */
2887 if (devmode.driverextra == 0) {
2888 devmode.nt_dev_private = NULL;
2892 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2894 SAFE_FREE(devmode.nt_dev_private);
2898 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2899 if (devmode.nt_dev_private)
2900 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2905 /****************************************************************************
2906 Allocate and initialize a new slot.
2907 ***************************************************************************/
2909 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2915 if ( !name || !data )
2918 /* allocate another slot in the NT_PRINTER_KEY array */
2920 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2921 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2927 key_index = data->num_keys;
2929 /* initialze new key */
2931 data->keys[key_index].name = talloc_strdup( data, name );
2933 werr = regval_ctr_init(data, &(data->keys[key_index].values));
2934 if (!W_ERROR_IS_OK(werr)) {
2940 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2945 /****************************************************************************
2946 search for a registry key name in the existing printer data
2947 ***************************************************************************/
2949 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2953 for ( i=0; i<data->num_keys; i++ ) {
2954 if ( strequal( data->keys[i].name, name ) ) {
2956 /* cleanup memory */
2958 TALLOC_FREE( data->keys[i].name );
2959 TALLOC_FREE( data->keys[i].values );
2961 /* if not the end of the array, move remaining elements down one slot */
2964 if ( data->num_keys && (i < data->num_keys) )
2965 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2972 return data->num_keys;
2975 /****************************************************************************
2976 search for a registry key name in the existing printer data
2977 ***************************************************************************/
2979 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2984 if ( !data || !name )
2987 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2989 /* loop over all existing keys */
2991 for ( i=0; i<data->num_keys; i++ ) {
2992 if ( strequal(data->keys[i].name, name) ) {
2993 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
3003 /****************************************************************************
3004 ***************************************************************************/
3006 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
3010 int num_subkeys = 0;
3012 fstring *subkeys_ptr = NULL;
3023 /* special case of asking for the top level printer data registry key names */
3025 if ( strlen(key) == 0 ) {
3026 for ( i=0; i<data->num_keys; i++ ) {
3028 /* found a match, so allocate space and copy the name */
3030 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3031 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3036 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
3043 /* asking for the subkeys of some key */
3044 /* subkey paths are stored in the key name using '\' as the delimiter */
3046 for ( i=0; i<data->num_keys; i++ ) {
3047 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
3049 /* if we found the exact key, then break */
3050 key_len = strlen( key );
3051 if ( strlen(data->keys[i].name) == key_len )
3054 /* get subkey path */
3056 p = data->keys[i].name + key_len;
3059 fstrcpy( subkeyname, p );
3060 if ( (p = strchr( subkeyname, '\\' )) )
3063 /* don't add a key more than once */
3065 for ( j=0; j<num_subkeys; j++ ) {
3066 if ( strequal( subkeys_ptr[j], subkeyname ) )
3070 if ( j != num_subkeys )
3073 /* found a match, so allocate space and copy the name */
3075 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3076 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3081 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
3087 /* return error if the key was not found */
3089 if ( i == data->num_keys ) {
3090 SAFE_FREE(subkeys_ptr);
3095 /* tag off the end */
3098 fstrcpy(subkeys_ptr[num_subkeys], "" );
3100 *subkeys = subkeys_ptr;
3106 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3109 regval_ctr_delvalue(ctr, val_name);
3110 regval_ctr_addvalue_sz(ctr, val_name, sz);
3113 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
3116 regval_ctr_delvalue(ctr, val_name);
3117 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
3118 (uint8 *) &dword, sizeof(dword));
3121 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
3124 uint8 bin_bool = (b ? 1 : 0);
3125 regval_ctr_delvalue(ctr, val_name);
3126 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
3127 (uint8 *) &bin_bool, sizeof(bin_bool));
3130 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3131 const char *multi_sz)
3138 regval_ctr_delvalue(ctr, val_name);
3139 regval_ctr_addvalue_multi_sz(ctr, val_name, a);
3142 /****************************************************************************
3143 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3145 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3146 * @return bool indicating success or failure
3147 ***************************************************************************/
3149 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
3151 struct regval_ctr *ctr = NULL;
3153 const char *dnssuffix;
3154 char *allocated_string = NULL;
3155 const char *ascii_str;
3158 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3159 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3160 ctr = info2->data->keys[i].values;
3162 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3163 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3165 /* we make the assumption that the netbios name is the same
3166 as the DNS name sinc ethe former will be what we used to
3169 dnssuffix = get_mydnsdomname(talloc_tos());
3170 if (dnssuffix && *dnssuffix) {
3171 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3173 fstrcpy( longname, global_myname() );
3176 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3178 if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3181 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3182 SAFE_FREE(allocated_string);
3184 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3185 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3186 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3187 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3188 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3189 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3190 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3191 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3192 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3194 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3195 (info2->attributes &
3196 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3198 switch (info2->attributes & 0x3) {
3200 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3203 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3206 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3209 ascii_str = "unknown";
3211 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3216 /*****************************************************************
3217 ****************************************************************/
3219 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3223 struct regval_ctr *ctr=NULL;
3225 /* find the DsSpooler key */
3226 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3227 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3228 ctr = info2->data->keys[i].values;
3230 regval_ctr_delvalue(ctr, "objectGUID");
3232 /* We used to store this as a REG_BINARY but that causes
3235 regval_ctr_addvalue_sz(ctr, "objectGUID",
3236 GUID_string(talloc_tos(), &guid));
3239 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3240 NT_PRINTER_INFO_LEVEL *printer)
3244 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3245 char *srv_dn_utf8, **srv_cn_utf8;
3248 const char *attrs[] = {"objectGUID", NULL};
3250 WERROR win_rc = WERR_OK;
3251 size_t converted_size;
3253 /* build the ads mods */
3254 ctx = talloc_init("nt_printer_publish_ads");
3259 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3261 /* figure out where to publish */
3262 ads_find_machine_acct(ads, &res, global_myname());
3264 /* We use ldap_get_dn here as we need the answer
3265 * in utf8 to call ldap_explode_dn(). JRA. */
3267 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3270 return WERR_SERVER_UNAVAILABLE;
3272 ads_msgfree(ads, res);
3273 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3276 ldap_memfree(srv_dn_utf8);
3277 return WERR_SERVER_UNAVAILABLE;
3279 /* Now convert to CH_UNIX. */
3280 if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3282 ldap_memfree(srv_dn_utf8);
3283 ldap_memfree(srv_cn_utf8);
3284 return WERR_SERVER_UNAVAILABLE;
3286 if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3288 ldap_memfree(srv_dn_utf8);
3289 ldap_memfree(srv_cn_utf8);
3290 TALLOC_FREE(srv_dn);
3291 return WERR_SERVER_UNAVAILABLE;
3294 ldap_memfree(srv_dn_utf8);
3295 ldap_memfree(srv_cn_utf8);
3297 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3298 if (!srv_cn_escaped) {
3300 return WERR_SERVER_UNAVAILABLE;
3302 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3303 if (!sharename_escaped) {
3304 SAFE_FREE(srv_cn_escaped);
3306 return WERR_SERVER_UNAVAILABLE;
3309 prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3311 SAFE_FREE(srv_cn_escaped);
3312 SAFE_FREE(sharename_escaped);
3314 mods = ads_init_mods(ctx);
3322 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3323 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3324 printer->info_2->sharename);
3327 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3328 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3330 for (i=0; mods[i] != 0; i++)
3332 mods[i] = (LDAPMod *)-1;
3333 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3336 if (!ADS_ERR_OK(ads_rc))
3337 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3339 /* retreive the guid and store it locally */
3340 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3342 ads_pull_guid(ads, res, &guid);
3343 ads_msgfree(ads, res);
3344 store_printer_guid(printer->info_2, guid);
3345 win_rc = mod_a_printer(printer, 2);
3352 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3353 NT_PRINTER_INFO_LEVEL *printer)
3356 LDAPMessage *res = NULL;
3357 char *prt_dn = NULL;
3359 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3361 /* remove the printer from the directory */
3362 ads_rc = ads_find_printer_on_server(ads, &res,
3363 printer->info_2->sharename, global_myname());
3365 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3366 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3368 ads_msgfree(ads, res);
3371 ads_rc = ads_del_dn(ads, prt_dn);
3372 TALLOC_FREE(prt_dn);
3376 ads_msgfree(ads, res);
3381 /****************************************************************************
3382 * Publish a printer in the directory
3384 * @param snum describing printer service
3385 * @return WERROR indicating status of publishing
3386 ***************************************************************************/
3388 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3391 ADS_STRUCT *ads = NULL;
3392 NT_PRINTER_INFO_LEVEL *printer = NULL;
3395 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3396 if (!W_ERROR_IS_OK(win_rc))
3400 case DSPRINT_PUBLISH:
3401 case DSPRINT_UPDATE:
3402 /* set the DsSpooler info and attributes */
3403 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3404 win_rc = WERR_NOMEM;
3408 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3410 case DSPRINT_UNPUBLISH:
3411 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3414 win_rc = WERR_NOT_SUPPORTED;
3418 win_rc = mod_a_printer(printer, 2);
3419 if (!W_ERROR_IS_OK(win_rc)) {
3420 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3424 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3426 DEBUG(3, ("ads_init() failed\n"));
3427 win_rc = WERR_SERVER_UNAVAILABLE;
3430 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3431 SAFE_FREE(ads->auth.password);
3432 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3435 /* ads_connect() will find the DC for us */
3436 ads_rc = ads_connect(ads);
3437 if (!ADS_ERR_OK(ads_rc)) {
3438 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3439 win_rc = WERR_ACCESS_DENIED;
3444 case DSPRINT_PUBLISH:
3445 case DSPRINT_UPDATE:
3446 win_rc = nt_printer_publish_ads(ads, printer);
3448 case DSPRINT_UNPUBLISH:
3449 win_rc = nt_printer_unpublish_ads(ads, printer);
3454 free_a_printer(&printer, 2);
3459 WERROR check_published_printers(void)
3462 ADS_STRUCT *ads = NULL;
3464 int n_services = lp_numservices();
3465 NT_PRINTER_INFO_LEVEL *printer = NULL;
3467 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3469 DEBUG(3, ("ads_init() failed\n"));
3470 return WERR_SERVER_UNAVAILABLE;
3472 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3473 SAFE_FREE(ads->auth.password);
3474 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3477 /* ads_connect() will find the DC for us */
3478 ads_rc = ads_connect(ads);
3479 if (!ADS_ERR_OK(ads_rc)) {
3480 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3482 ads_kdestroy("MEMORY:prtpub_cache");
3483 return WERR_ACCESS_DENIED;
3486 for (snum = 0; snum < n_services; snum++) {
3487 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3490 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3491 lp_servicename(snum))) &&
3492 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3493 nt_printer_publish_ads(ads, printer);
3495 free_a_printer(&printer, 2);
3499 ads_kdestroy("MEMORY:prtpub_cache");
3503 bool is_printer_published(Printer_entry *print_hnd, int snum,
3506 NT_PRINTER_INFO_LEVEL *printer = NULL;
3507 struct regval_ctr *ctr;
3508 struct regval_blob *guid_val;
3514 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3516 if (!W_ERROR_IS_OK(win_rc) ||
3517 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3518 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3519 !(ctr = printer->info_2->data->keys[i].values) ||
3520 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3522 free_a_printer(&printer, 2);
3526 /* fetching printer guids really ought to be a separate function. */
3531 /* We used to store the guid as REG_BINARY, then swapped
3532 to REG_SZ for Vista compatibility so check for both */
3534 switch ( regval_type(guid_val) ){
3536 blob = data_blob_const(regval_data_p(guid_val),
3537 regval_size(guid_val));
3538 pull_reg_sz(talloc_tos(), &blob, (const char **)&guid_str);
3539 ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3540 talloc_free(guid_str);
3543 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3547 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3550 DEBUG(0,("is_printer_published: GUID value stored as "
3551 "invaluid type (%d)\n", regval_type(guid_val) ));
3556 free_a_printer(&printer, 2);
3560 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3565 WERROR check_published_printers(void)
3570 bool is_printer_published(Printer_entry *print_hnd, int snum,
3575 #endif /* HAVE_ADS */
3577 /****************************************************************************
3578 ***************************************************************************/
3580 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3582 NT_PRINTER_DATA *data;
3584 int removed_keys = 0;
3588 empty_slot = data->num_keys;
3591 return WERR_INVALID_PARAM;
3593 /* remove all keys */
3595 if ( !strlen(key) ) {
3597 TALLOC_FREE( data );
3601 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3607 /* remove a specific key (and all subkeys) */
3609 for ( i=0; i<data->num_keys; i++ ) {
3610 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3611 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3612 data->keys[i].name));
3614 TALLOC_FREE( data->keys[i].name );
3615 TALLOC_FREE( data->keys[i].values );
3617 /* mark the slot as empty */
3619 ZERO_STRUCTP( &data->keys[i] );
3623 /* find the first empty slot */
3625 for ( i=0; i<data->num_keys; i++ ) {
3626 if ( !data->keys[i].name ) {
3633 if ( i == data->num_keys )
3634 /* nothing was removed */
3635 return WERR_INVALID_PARAM;
3637 /* move everything down */
3639 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3640 if ( data->keys[i].name ) {
3641 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3642 ZERO_STRUCTP( &data->keys[i] );
3650 data->num_keys -= removed_keys;
3652 /* sanity check to see if anything is left */
3654 if ( !data->num_keys ) {
3655 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3657 SAFE_FREE( data->keys );
3658 ZERO_STRUCTP( data );
3664 /****************************************************************************
3665 ***************************************************************************/
3667 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3669 WERROR result = WERR_OK;
3672 /* we must have names on non-zero length */
3674 if ( !key || !*key|| !value || !*value )
3675 return WERR_INVALID_NAME;
3677 /* find the printer key first */
3679 key_index = lookup_printerkey( p2->data, key );
3680 if ( key_index == -1 )
3683 /* make sure the value exists so we can return the correct error code */
3685 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3686 return WERR_BADFILE;
3688 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3690 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3696 /****************************************************************************
3697 ***************************************************************************/
3699 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3700 uint32 type, uint8 *data, int real_len )
3702 WERROR result = WERR_OK;
3705 /* we must have names on non-zero length */
3707 if ( !key || !*key|| !value || !*value )
3708 return WERR_INVALID_NAME;
3710 /* find the printer key first */
3712 key_index = lookup_printerkey( p2->data, key );
3713 if ( key_index == -1 )
3714 key_index = add_new_printer_key( p2->data, key );
3716 if ( key_index == -1 )
3719 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3720 type, data, real_len );
3722 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3723 key, value, type, real_len ));
3728 /****************************************************************************
3729 ***************************************************************************/
3731 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3735 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3738 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3741 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3744 /****************************************************************************
3745 Unpack a list of registry values frem the TDB
3746 ***************************************************************************/
3748 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3753 const char *valuename = NULL;
3754 const char *keyname = NULL;
3758 struct regval_blob *regval_p;
3761 /* add the "PrinterDriverData" key first for performance reasons */
3763 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3765 /* loop and unpack the rest of the registry values */
3769 /* check to see if there are any more registry values */
3772 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3776 /* unpack the next regval */
3778 len += tdb_unpack(buf+len, buflen-len, "fdB",
3784 /* lookup for subkey names which have a type of REG_NONE */
3785 /* there's no data with this entry */
3787 if ( type == REG_NONE ) {
3788 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3789 add_new_printer_key( printer_data, string );
3794 * break of the keyname from the value name.
3795 * Valuenames can have embedded '\'s so be careful.
3796 * only support one level of keys. See the
3797 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3801 str = strchr_m( string, '\\');
3803 /* Put in "PrinterDriverData" is no key specified */
3806 keyname = SPOOL_PRINTERDATA_KEY;
3815 /* see if we need a new key */
3817 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3818 key_index = add_new_printer_key( printer_data, keyname );
3820 if ( key_index == -1 ) {
3821 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3826 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3828 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3829 Thanks to Martin Zielinski for the hint. */
3831 if ( type == REG_BINARY &&
3832 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3833 strequal( valuename, "objectGUID" ) )
3837 /* convert the GUID to a UNICODE string */
3839 memcpy( &guid, data_p, sizeof(struct GUID) );
3841 regval_ctr_addvalue_sz(printer_data->keys[key_index].values,
3843 GUID_string(talloc_tos(), &guid));
3848 regval_ctr_addvalue( printer_data->keys[key_index].values,
3849 valuename, type, data_p,
3853 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3860 /****************************************************************************
3861 ***************************************************************************/
3863 static char *win_driver;
3864 static char *os2_driver;
3866 static const char *get_win_driver(void)
3868 if (win_driver == NULL) {
3874 static const char *get_os2_driver(void)
3876 if (os2_driver == NULL) {
3882 static bool set_driver_mapping(const char *from, const char *to)
3884 SAFE_FREE(win_driver);
3885 SAFE_FREE(os2_driver);
3887 win_driver = SMB_STRDUP(from);
3888 os2_driver = SMB_STRDUP(to);
3890 if (win_driver == NULL || os2_driver == NULL) {
3891 SAFE_FREE(win_driver);
3892 SAFE_FREE(os2_driver);
3898 static void map_to_os2_driver(fstring drivername)
3900 char *mapfile = lp_os2_driver_map();
3901 char **lines = NULL;
3905 if (!strlen(drivername))
3911 if (strequal(drivername, get_win_driver())) {
3912 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3913 drivername, get_os2_driver()));
3914 fstrcpy(drivername, get_os2_driver());
3918 lines = file_lines_load(mapfile, &numlines,0,NULL);
3919 if (numlines == 0 || lines == NULL) {
3920 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3925 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3927 for( i = 0; i < numlines; i++) {
3928 char *nt_name = lines[i];
3929 char *os2_name = strchr(nt_name,'=');
3936 while (isspace(*nt_name))
3939 if (!*nt_name || strchr("#;",*nt_name))
3943 int l = strlen(nt_name);
3944 while (l && isspace(nt_name[l-1])) {
3950 while (isspace(*os2_name))
3954 int l = strlen(os2_name);
3955 while (l && isspace(os2_name[l-1])) {
3961 if (strequal(nt_name,drivername)) {
3962 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3963 set_driver_mapping(drivername,os2_name);
3964 fstrcpy(drivername,os2_name);
3976 * @brief Map a Windows driver to a OS/2 driver.
3978 * @param[in] mem_ctx The memory context to use.
3980 * @param[in,out] pdrivername The drivername of Windows to remap.
3982 * @return WERR_OK on success, a corresponding WERROR on failure.
3984 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
3986 const char *mapfile = lp_os2_driver_map();
3987 char **lines = NULL;
3988 const char *drivername;
3992 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
3993 return WERR_INVALID_PARAMETER;
3996 drivername = *pdrivername;
3998 if (mapfile[0] == '\0') {
3999 return WERR_BADFILE;
4002 if (strequal(drivername, get_win_driver())) {
4003 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
4004 drivername, get_os2_driver()));
4005 drivername = talloc_strdup(mem_ctx, get_os2_driver());
4006 if (drivername == NULL) {
4009 *pdrivername = drivername;
4013 lines = file_lines_load(mapfile, &numlines, 0, NULL);
4014 if (numlines == 0 || lines == NULL) {
4015 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
4020 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
4022 for( i = 0; i < numlines; i++) {
4023 char *nt_name = lines[i];
4024 char *os2_name = strchr(nt_name, '=');
4026 if (os2_name == NULL) {
4032 while (isspace(*nt_name)) {
4036 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
4041 int l = strlen(nt_name);
4042 while (l && isspace(nt_name[l - 1])) {
4048 while (isspace(*os2_name)) {
4053 int l = strlen(os2_name);
4054 while (l && isspace(os2_name[l-1])) {
4060 if (strequal(nt_name, drivername)) {
4061 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
4062 set_driver_mapping(drivername, os2_name);
4063 drivername = talloc_strdup(mem_ctx, os2_name);
4065 if (drivername == NULL) {
4068 *pdrivername = drivername;
4077 /****************************************************************************
4078 Get a default printer info 2 struct.
4079 ****************************************************************************/
4081 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
4082 const char *servername,
4083 const char* sharename,
4086 int snum = lp_servicenumber(sharename);
4088 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4089 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4090 servername, sharename);
4091 fstrcpy(info->sharename, sharename);
4092 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
4094 /* by setting the driver name to an empty string, a local NT admin
4095 can now run the **local** APW to install a local printer driver
4096 for a Samba shared printer in 2.2. Without this, drivers **must** be
4097 installed on the Samba server for NT clients --jerry */
4098 #if 0 /* JERRY --do not uncomment-- */
4099 if (!*info->drivername)
4100 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
4104 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
4106 strlcpy(info->comment, "", sizeof(info->comment));
4107 fstrcpy(info->printprocessor, "winprint");
4108 fstrcpy(info->datatype, "RAW");
4111 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4112 /* Pull the location and comment strings from cups if we don't
4114 if ( !strlen(info->location) || !strlen(info->comment) ) {
4115 char *comment = NULL;
4116 char *location = NULL;
4117 if (cups_pull_comment_location(info, info->sharename,
4118 &comment, &location)) {
4119 strlcpy(info->comment, comment, sizeof(info->comment));
4120 fstrcpy(info->location, location);
4121 TALLOC_FREE(comment);
4122 TALLOC_FREE(location);
4128 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
4130 info->starttime = 0; /* Minutes since 12:00am GMT */
4131 info->untiltime = 0; /* Minutes since 12:00am GMT */
4133 info->default_priority = 1;
4134 info->setuptime = (uint32)time(NULL);
4137 * I changed this as I think it is better to have a generic
4138 * DEVMODE than to crash Win2k explorer.exe --jerry
4139 * See the HP Deskjet 990c Win2k drivers for an example.
4141 * However the default devmode appears to cause problems
4142 * with the HP CLJ 8500 PCL driver. Hence the addition of
4143 * the "default devmode" parameter --jerry 22/01/2002
4146 if (lp_default_devmode(snum)) {
4147 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
4151 info->devmode = NULL;
4154 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4158 info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
4163 add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
4169 free_nt_devicemode(&info->devmode);
4171 return WERR_ACCESS_DENIED;
4174 /****************************************************************************
4175 ****************************************************************************/
4177 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
4178 const char *servername,
4179 const char *sharename,
4183 int snum = lp_servicenumber(sharename);
4184 TDB_DATA kbuf, dbuf;
4185 fstring printername;
4186 char adevice[MAXDEVICENAME];
4187 char *comment = NULL;
4189 kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4191 dbuf = tdb_fetch(tdb_printers, kbuf);
4193 return get_a_printer_2_default(info, servername,
4194 sharename, get_loc_com);
4197 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4200 &info->default_priority,
4207 &info->c_setprinter,
4217 info->printprocessor,
4222 strlcpy(info->comment, comment, sizeof(info->comment));
4226 /* Samba has to have shared raw drivers. */
4227 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4228 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4230 /* Restore the stripped strings. */
4231 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4233 if ( lp_force_printername(snum) ) {
4234 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4236 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4239 fstrcpy(info->printername, printername);
4242 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4243 /* Pull the location and comment strings from cups if we don't
4245 if ( !strlen(info->location) || !strlen(info->comment) ) {
4246 char *location = NULL;
4248 if (cups_pull_comment_location(info, info->sharename,
4249 &comment, &location)) {
4250 strlcpy(info->comment, comment, sizeof(info->comment));
4251 fstrcpy(info->location, location);
4252 TALLOC_FREE(comment);
4253 TALLOC_FREE(location);
4259 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4262 * Some client drivers freak out if there is a NULL devmode
4263 * (probably the driver is not checking before accessing
4264 * the devmode pointer) --jerry
4266 * See comments in get_a_printer_2_default()
4269 if (lp_default_devmode(snum) && !info->devmode) {
4270 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4272 info->devmode = construct_nt_devicemode(printername);
4275 slprintf( adevice, sizeof(adevice), "%s", info->printername );
4276 if (info->devmode) {
4277 fstrcpy(info->devmode->devicename, adevice);
4280 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4281 DEBUG(0,("unpack_values: talloc() failed!\n"));
4282 SAFE_FREE(dbuf.dptr);
4285 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4287 /* This will get the current RPC talloc context, but we should be
4288 passing this as a parameter... fixme... JRA ! */
4290 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4291 SAFE_FREE(dbuf.dptr);
4295 /* Fix for OS/2 drivers. */
4297 if (get_remote_arch() == RA_OS2) {
4298 map_to_os2_driver(info->drivername);
4301 SAFE_FREE(dbuf.dptr);
4303 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4304 sharename, info->printername, info->drivername));
4309 /****************************************************************************
4310 Debugging function, dump at level 6 the struct in the logs.
4311 ****************************************************************************/
4312 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4315 NT_PRINTER_INFO_LEVEL_2 *info2;
4317 DEBUG(106,("Dumping printer at level [%d]\n", level));
4322 if (printer->info_2 == NULL)
4326 info2=printer->info_2;
4328 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4329 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4330 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4331 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4332 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4333 DEBUGADD(106,("status:[%d]\n", info2->status));
4334 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4335 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4336 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4337 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4338 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4340 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4341 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4342 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4343 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4344 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4345 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4346 DEBUGADD(106,("location:[%s]\n", info2->location));
4347 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4348 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4349 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4350 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4356 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4364 /****************************************************************************
4365 Update the changeid time.
4366 This is SO NASTY as some drivers need this to change, others need it
4367 static. This value will change every second, and I must hope that this
4368 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4370 ****************************************************************************/
4372 static uint32 rev_changeid(void)
4376 get_process_uptime(&tv);
4379 /* Return changeid as msec since spooler restart */
4380 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4383 * This setting seems to work well but is too untested
4384 * to replace the above calculation. Left in for experiementation
4385 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4387 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4393 * The function below are the high level ones.
4394 * only those ones must be called from the spoolss code.
4398 /****************************************************************************
4399 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4400 ****************************************************************************/
4402 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4406 dump_a_printer(printer, level);
4412 * Update the changestamp. Emperical tests show that the
4413 * ChangeID is always updated,but c_setprinter is
4414 * global spooler variable (not per printer).
4417 /* ChangeID **must** be increasing over the lifetime
4418 of client's spoolss service in order for the
4419 client's cache to show updates */
4421 printer->info_2->changeid = rev_changeid();
4424 * Because one day someone will ask:
4425 * NT->NT An admin connection to a remote
4426 * printer show changes imeediately in
4427 * the properities dialog
4429 * A non-admin connection will only show the
4430 * changes after viewing the properites page
4431 * 2 times. Seems to be related to a
4432 * race condition in the client between the spooler
4433 * updating the local cache and the Explorer.exe GUI
4434 * actually displaying the properties.
4436 * This is fixed in Win2k. admin/non-admin
4437 * connections both display changes immediately.
4442 result=update_a_printer_2(printer->info_2);
4446 result=WERR_UNKNOWN_LEVEL;
4453 /****************************************************************************
4454 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4456 Previously the code had a memory allocation problem because it always
4457 used the TALLOC_CTX from the Printer_entry*. This context lasts
4458 as a long as the original handle is open. So if the client made a lot
4459 of getprinter[data]() calls, the memory usage would climb. Now we use
4460 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4461 still use the Printer_entry->ctx for maintaining the cache copy though
4462 since that object must live as long as the handle by definition.
4465 ****************************************************************************/
4467 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4468 const char *sharename, bool get_loc_com)
4473 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4475 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4476 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4482 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4483 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4484 TALLOC_FREE( *pp_printer );
4489 fstrcpy( servername, print_hnd->servername );
4491 fstrcpy( servername, "%L" );
4492 standard_sub_basic( "", "", servername,
4493 sizeof(servername)-1 );
4496 result = get_a_printer_2( (*pp_printer)->info_2,
4497 servername, sharename, get_loc_com);
4499 /* we have a new printer now. Save it with this handle */
4501 if ( !W_ERROR_IS_OK(result) ) {
4502 TALLOC_FREE( *pp_printer );
4503 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4504 sharename, (unsigned int)level, win_errstr(result)));
4508 dump_a_printer( *pp_printer, level);
4513 TALLOC_FREE( *pp_printer );
4514 return WERR_UNKNOWN_LEVEL;
4520 WERROR get_a_printer( Printer_entry *print_hnd,
4521 NT_PRINTER_INFO_LEVEL **pp_printer,
4523 const char *sharename)
4525 return get_a_printer_internal(print_hnd, pp_printer, level,
4529 WERROR get_a_printer_search( Printer_entry *print_hnd,
4530 NT_PRINTER_INFO_LEVEL **pp_printer,
4532 const char *sharename)
4534 return get_a_printer_internal(print_hnd, pp_printer, level,
4538 /****************************************************************************
4539 Deletes a NT_PRINTER_INFO_LEVEL struct.
4540 ****************************************************************************/
4542 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4544 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4551 if ( printer->info_2 )
4552 free_nt_printer_info_level_2(&printer->info_2);
4556 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4560 TALLOC_FREE(*pp_printer);
4565 /****************************************************************************
4566 ****************************************************************************/
4568 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
4569 struct spoolss_DriverInfo8 *_info8)
4571 struct spoolss_DriverInfo8 info8;
4577 info8.version = r->info.info3->version;
4578 info8.driver_name = r->info.info3->driver_name;
4579 info8.architecture = r->info.info3->architecture;
4580 info8.driver_path = r->info.info3->driver_path;
4581 info8.data_file = r->info.info3->data_file;
4582 info8.config_file = r->info.info3->config_file;
4583 info8.help_file = r->info.info3->help_file;
4584 info8.monitor_name = r->info.info3->monitor_name;
4585 info8.default_datatype = r->info.info3->default_datatype;
4586 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
4587 info8.dependent_files = r->info.info3->dependent_files->string;
4591 info8.version = r->info.info6->version;
4592 info8.driver_name = r->info.info6->driver_name;
4593 info8.architecture = r->info.info6->architecture;
4594 info8.driver_path = r->info.info6->driver_path;
4595 info8.data_file = r->info.info6->data_file;
4596 info8.config_file = r->info.info6->config_file;
4597 info8.help_file = r->info.info6->help_file;
4598 info8.monitor_name = r->info.info6->monitor_name;
4599 info8.default_datatype = r->info.info6->default_datatype;
4600 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
4601 info8.dependent_files = r->info.info6->dependent_files->string;
4603 info8.driver_date = r->info.info6->driver_date;
4604 info8.driver_version = r->info.info6->driver_version;
4605 info8.manufacturer_name = r->info.info6->manufacturer_name;
4606 info8.manufacturer_url = r->info.info6->manufacturer_url;
4607 info8.hardware_id = r->info.info6->hardware_id;
4608 info8.provider = r->info.info6->provider;
4611 info8.version = r->info.info8->version;
4612 info8.driver_name = r->info.info8->driver_name;
4613 info8.architecture = r->info.info8->architecture;
4614 info8.driver_path = r->info.info8->driver_path;
4615 info8.data_file = r->info.info8->data_file;
4616 info8.config_file = r->info.info8->config_file;
4617 info8.help_file = r->info.info8->help_file;
4618 info8.monitor_name = r->info.info8->monitor_name;
4619 info8.default_datatype = r->info.info8->default_datatype;
4620 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
4621 info8.dependent_files = r->info.info8->dependent_files->string;
4623 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
4624 info8.previous_names = r->info.info8->previous_names->string;
4626 info8.driver_date = r->info.info8->driver_date;
4627 info8.driver_version = r->info.info8->driver_version;
4628 info8.manufacturer_name = r->info.info8->manufacturer_name;
4629 info8.manufacturer_url = r->info.info8->manufacturer_url;
4630 info8.hardware_id = r->info.info8->hardware_id;
4631 info8.provider = r->info.info8->provider;
4632 info8.print_processor = r->info.info8->print_processor;
4633 info8.vendor_setup = r->info.info8->vendor_setup;
4634 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
4635 info8.color_profiles = r->info.info8->color_profiles->string;
4637 info8.inf_path = r->info.info8->inf_path;
4638 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
4639 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
4640 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
4642 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
4643 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
4655 uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx,
4656 struct spoolss_AddDriverInfoCtr *r,
4660 struct spoolss_DriverInfo8 info8;
4664 DEBUG(10,("adding a printer at level [%d]\n", r->level));
4666 if (!driver_info_ctr_to_info8(r, &info8)) {
4670 *driver_name = talloc_strdup(mem_ctx, info8.driver_name);
4671 if (!*driver_name) {
4674 *version = info8.version;
4676 return add_a_printer_driver_8(&info8);
4679 /****************************************************************************
4680 ****************************************************************************/
4682 WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx,
4683 struct spoolss_DriverInfo8 **driver,
4684 const char *drivername, const char *architecture,
4688 struct spoolss_DriverInfo3 info3;
4689 struct spoolss_DriverInfo8 *info8;
4693 /* Sometime we just want any version of the driver */
4695 if (version == DRIVER_ANY_VERSION) {
4696 /* look for Win2k first and then for NT4 */
4697 result = get_a_printer_driver_3(mem_ctx,
4701 if (!W_ERROR_IS_OK(result)) {
4702 result = get_a_printer_driver_3(mem_ctx,
4708 result = get_a_printer_driver_3(mem_ctx,
4715 if (!W_ERROR_IS_OK(result)) {
4719 info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8);
4724 info8->version = info3.version;
4725 info8->driver_name = info3.driver_name;
4726 info8->architecture = info3.architecture;
4727 info8->driver_path = info3.driver_path;
4728 info8->data_file = info3.data_file;
4729 info8->config_file = info3.config_file;
4730 info8->help_file = info3.help_file;
4731 info8->dependent_files = info3.dependent_files;
4732 info8->monitor_name = info3.monitor_name;
4733 info8->default_datatype = info3.default_datatype;
4740 /****************************************************************************
4741 ****************************************************************************/
4743 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver)
4745 talloc_free(driver);
4750 /****************************************************************************
4751 Determine whether or not a particular driver is currently assigned
4753 ****************************************************************************/
4755 bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r)
4758 int n_services = lp_numservices();
4759 NT_PRINTER_INFO_LEVEL *printer = NULL;
4760 bool in_use = False;
4766 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4768 /* loop through the printers.tdb and check for the drivername */
4770 for (snum=0; snum<n_services && !in_use; snum++) {
4771 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4774 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4777 if (strequal(r->driver_name, printer->info_2->drivername))
4780 free_a_printer( &printer, 2 );
4783 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4786 struct spoolss_DriverInfo8 *d;
4789 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
4791 /* we can still remove the driver if there is one of
4792 "Windows NT x86" version 2 or 3 left */
4794 if (!strequal("Windows NT x86", r->architecture)) {
4795 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION);
4798 switch (r->version) {
4800 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3);
4803 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2);
4806 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4808 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4813 /* now check the error code */
4815 if ( W_ERROR_IS_OK(werr) ) {
4816 /* it's ok to remove the driver, we have other architctures left */
4818 free_a_printer_driver(d);
4822 /* report that the driver is not in use by default */
4828 /**********************************************************************
4829 Check to see if a ogiven file is in use by *info
4830 *********************************************************************/
4832 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
4839 /* mz: skip files that are in the list but already deleted */
4840 if (!file || !file[0]) {
4844 if (strequal(file, info->driver_path))
4847 if (strequal(file, info->data_file))
4850 if (strequal(file, info->config_file))
4853 if (strequal(file, info->help_file))
4856 /* see of there are any dependent files to examine */
4858 if (!info->dependent_files)
4861 while (info->dependent_files[i] && *info->dependent_files[i]) {
4862 if (strequal(file, info->dependent_files[i]))
4871 /**********************************************************************
4872 Utility function to remove the dependent file pointed to by the
4873 input parameter from the list
4874 *********************************************************************/
4876 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
4879 /* bump everything down a slot */
4881 while (files && files[idx+1]) {
4882 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
4891 /**********************************************************************
4892 Check if any of the files used by src are also used by drv
4893 *********************************************************************/
4895 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
4896 struct spoolss_DriverInfo8 *src,
4897 const struct spoolss_DriverInfo8 *drv)
4899 bool in_use = False;
4905 /* check each file. Remove it from the src structure if it overlaps */
4907 if (drv_file_in_use(src->driver_path, drv)) {
4909 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
4910 src->driver_path = talloc_strdup(mem_ctx, "");
4911 if (!src->driver_path) { return false; }
4914 if (drv_file_in_use(src->data_file, drv)) {
4916 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
4917 src->data_file = talloc_strdup(mem_ctx, "");
4918 if (!src->data_file) { return false; }
4921 if (drv_file_in_use(src->config_file, drv)) {
4923 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
4924 src->config_file = talloc_strdup(mem_ctx, "");
4925 if (!src->config_file) { return false; }
4928 if (drv_file_in_use(src->help_file, drv)) {
4930 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
4931 src->help_file = talloc_strdup(mem_ctx, "");
4932 if (!src->help_file) { return false; }
4935 /* are there any dependentfiles to examine? */
4937 if (!src->dependent_files)
4940 while (src->dependent_files[i] && *src->dependent_files[i]) {
4941 if (drv_file_in_use(src->dependent_files[i], drv)) {
4943 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
4944 trim_dependent_file(mem_ctx, src->dependent_files, i);
4952 /****************************************************************************
4953 Determine whether or not a particular driver files are currently being
4954 used by any other driver.
4956 Return value is True if any files were in use by other drivers
4957 and False otherwise.
4959 Upon return, *info has been modified to only contain the driver files
4960 which are not in use
4964 This needs to check all drivers to ensure that all files in use
4965 have been removed from *info, not just the ones in the first
4967 ****************************************************************************/
4969 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
4970 struct spoolss_DriverInfo8 *info)
4975 fstring *list = NULL;
4976 struct spoolss_DriverInfo8 *driver;
4977 bool in_use = false;
4982 version = info->version;
4984 /* loop over all driver versions */
4986 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4988 /* get the list of drivers */
4991 ndrivers = get_ntdrivers(&list, info->architecture, version);
4993 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4994 ndrivers, info->architecture, version));
4996 /* check each driver for overlap in files */
4998 for (i=0; i<ndrivers; i++) {
4999 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5003 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, list[i], info->architecture, version))) {
5008 /* check if d2 uses any files from d1 */
5009 /* only if this is a different driver than the one being deleted */
5011 if (!strequal(info->driver_name, driver->driver_name)) {
5012 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
5013 /* mz: Do not instantly return -
5014 * we need to ensure this file isn't
5015 * also in use by other drivers. */
5020 free_a_printer_driver(driver);
5025 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5030 static NTSTATUS driver_unlink_internals(connection_struct *conn,
5033 struct smb_filename *smb_fname = NULL;
5036 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
5038 if (!NT_STATUS_IS_OK(status)) {
5042 status = unlink_internals(conn, NULL, 0, smb_fname, false);
5044 TALLOC_FREE(smb_fname);
5048 /****************************************************************************
5049 Actually delete the driver files. Make sure that
5050 printer_driver_files_in_use() return False before calling
5052 ****************************************************************************/
5054 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
5055 const struct spoolss_DriverInfo8 *r)
5060 connection_struct *conn;
5063 fstring printdollar;
5064 int printdollar_snum;
5071 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
5072 r->driver_name, r->version));
5074 fstrcpy(printdollar, "print$");
5076 printdollar_snum = find_service(printdollar);
5077 if (printdollar_snum == -1) {
5081 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5082 lp_pathname(printdollar_snum),
5083 rpc_pipe->server_info, &oldcwd);
5084 if (!NT_STATUS_IS_OK(nt_status)) {
5085 DEBUG(0,("delete_driver_files: create_conn_struct "
5086 "returned %s\n", nt_errstr(nt_status)));
5090 if ( !CAN_WRITE(conn) ) {
5091 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5095 /* now delete the files; must strip the '\print$' string from
5098 if (r->driver_path && r->driver_path[0]) {
5099 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
5101 DEBUG(10,("deleting driverfile [%s]\n", s));
5102 driver_unlink_internals(conn, file);
5106 if (r->config_file && r->config_file[0]) {
5107 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
5109 DEBUG(10,("deleting configfile [%s]\n", s));
5110 driver_unlink_internals(conn, file);
5114 if (r->data_file && r->data_file[0]) {
5115 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
5117 DEBUG(10,("deleting datafile [%s]\n", s));
5118 driver_unlink_internals(conn, file);
5122 if (r->help_file && r->help_file[0]) {
5123 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
5125 DEBUG(10,("deleting helpfile [%s]\n", s));
5126 driver_unlink_internals(conn, file);
5130 /* check if we are done removing files */
5132 if (r->dependent_files) {
5133 while (r->dependent_files[i] && r->dependent_files[i][0]) {
5136 /* bypass the "\print$" portion of the path */
5138 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
5140 DEBUG(10,("deleting dependent file [%s]\n", file));
5141 driver_unlink_internals(conn, file);
5153 vfs_ChDir(conn, oldcwd);
5159 /****************************************************************************
5160 Remove a printer driver from the TDB. This assumes that the the driver was
5161 previously looked up.
5162 ***************************************************************************/
5164 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5165 const struct spoolss_DriverInfo8 *r,
5166 uint32 version, bool delete_files )
5172 /* delete the tdb data first */
5174 arch = get_short_archi(r->architecture);
5176 return WERR_UNKNOWN_PRINTER_DRIVER;
5178 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5179 arch, version, r->driver_name) < 0) {
5183 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5184 key, delete_files ? "TRUE" : "FALSE" ));
5186 /* check if the driver actually exists for this environment */
5188 dbuf = tdb_fetch_bystring( tdb_drivers, key );
5190 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5192 return WERR_UNKNOWN_PRINTER_DRIVER;
5195 SAFE_FREE( dbuf.dptr );
5197 /* ok... the driver exists so the delete should return success */
5199 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5200 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5202 return WERR_ACCESS_DENIED;
5206 * now delete any associated files if delete_files == True
5207 * even if this part failes, we return succes because the
5208 * driver doesn not exist any more
5212 delete_driver_files(rpc_pipe, r);
5214 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5220 /****************************************************************************
5221 Store a security desc for a printer.
5222 ****************************************************************************/
5224 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
5226 struct sec_desc_buf *new_secdesc_ctr = NULL;
5227 struct sec_desc_buf *old_secdesc_ctr = NULL;
5228 TALLOC_CTX *mem_ctx = NULL;
5235 mem_ctx = talloc_init("nt_printing_setsec");
5236 if (mem_ctx == NULL)
5239 /* The old owner and group sids of the security descriptor are not
5240 present when new ACEs are added or removed by changing printer
5241 permissions through NT. If they are NULL in the new security
5242 descriptor then copy them over from the old one. */
5244 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5245 struct dom_sid *owner_sid, *group_sid;
5246 struct security_acl *dacl, *sacl;
5247 struct security_descriptor *psd = NULL;
5250 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5251 status = WERR_NOMEM;
5255 /* Pick out correct owner and group sids */
5257 owner_sid = secdesc_ctr->sd->owner_sid ?
5258 secdesc_ctr->sd->owner_sid :
5259 old_secdesc_ctr->sd->owner_sid;
5261 group_sid = secdesc_ctr->sd->group_sid ?
5262 secdesc_ctr->sd->group_sid :
5263 old_secdesc_ctr->sd->group_sid;
5265 dacl = secdesc_ctr->sd->dacl ?
5266 secdesc_ctr->sd->dacl :
5267 old_secdesc_ctr->sd->dacl;
5269 sacl = secdesc_ctr->sd->sacl ?
5270 secdesc_ctr->sd->sacl :
5271 old_secdesc_ctr->sd->sacl;
5273 /* Make a deep copy of the security descriptor */
5275 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5276 owner_sid, group_sid,
5282 status = WERR_NOMEM;
5286 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5289 if (!new_secdesc_ctr) {
5290 new_secdesc_ctr = secdesc_ctr;
5293 /* Store the security descriptor in a tdb */
5295 nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5296 &blob.data, &blob.length);
5297 if (!NT_STATUS_IS_OK(nt_status)) {
5298 status = ntstatus_to_werror(nt_status);
5302 kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5304 dbuf.dptr = (unsigned char *)blob.data;
5305 dbuf.dsize = blob.length;
5307 if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5310 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5311 status = WERR_BADFUNC;
5314 /* Free malloc'ed memory */
5315 talloc_free(blob.data);
5320 talloc_destroy(mem_ctx);
5324 /****************************************************************************
5325 Construct a default security descriptor buffer for a printer.
5326 ****************************************************************************/
5328 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
5330 struct security_ace ace[7]; /* max number of ace entries */
5333 struct security_acl *psa = NULL;
5334 struct sec_desc_buf *sdb = NULL;
5335 struct security_descriptor *psd = NULL;
5336 struct dom_sid adm_sid;
5339 /* Create an ACE where Everyone is allowed to print */
5341 sa = PRINTER_ACE_PRINT;
5342 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5343 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5345 /* Add the domain admins group if we are a DC */
5348 struct dom_sid domadmins_sid;
5350 sid_compose(&domadmins_sid, get_global_sam_sid(),
5353 sa = PRINTER_ACE_FULL_CONTROL;
5354 init_sec_ace(&ace[i++], &domadmins_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++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5358 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5360 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5361 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
5363 sa = PRINTER_ACE_FULL_CONTROL;
5364 init_sec_ace(&ace[i++], &adm_sid,
5365 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5366 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5367 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5368 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5371 /* add BUILTIN\Administrators as FULL CONTROL */
5373 sa = PRINTER_ACE_FULL_CONTROL;
5374 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5375 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5376 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5377 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5378 SEC_ACE_TYPE_ACCESS_ALLOWED,
5379 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5381 /* add BUILTIN\Print Operators as FULL CONTROL */
5383 sa = PRINTER_ACE_FULL_CONTROL;
5384 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
5385 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5386 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5387 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
5388 SEC_ACE_TYPE_ACCESS_ALLOWED,
5389 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5391 /* Make the security descriptor owned by the BUILTIN\Administrators */
5393 /* The ACL revision number in rpc_secdesc.h differs from the one
5394 created by NT when setting ACE entries in printer
5395 descriptors. NT4 complains about the property being edited by a
5398 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5399 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
5400 &global_sid_Builtin_Administrators,
5401 &global_sid_Builtin_Administrators,
5402 NULL, psa, &sd_size);
5406 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5410 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5412 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5413 (unsigned int)sd_size));
5418 /****************************************************************************
5419 Get a security desc for a printer.
5420 ****************************************************************************/
5422 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
5430 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5431 sharename = temp + 1;
5434 /* Fetch security descriptor from tdb */
5436 kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5438 dbuf = tdb_fetch(tdb_printers, kbuf);
5441 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5443 SAFE_FREE(dbuf.dptr);
5445 if (NT_STATUS_IS_OK(status)) {
5450 *secdesc_ctr = construct_default_printer_sdb(ctx);
5451 if (!*secdesc_ctr) {
5455 status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5456 &blob.data, &blob.length);
5457 if (NT_STATUS_IS_OK(status)) {
5458 dbuf.dptr = (unsigned char *)blob.data;
5459 dbuf.dsize = blob.length;
5460 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5461 talloc_free(blob.data);
5464 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5465 this security descriptor has been created when winbindd was
5466 down. Take ownership of security descriptor. */
5468 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5469 struct dom_sid owner_sid;
5471 /* Change sd owner to workgroup administrator */
5473 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5474 struct sec_desc_buf *new_secdesc_ctr = NULL;
5475 struct security_descriptor *psd = NULL;
5480 sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
5482 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5484 (*secdesc_ctr)->sd->group_sid,
5485 (*secdesc_ctr)->sd->sacl,
5486 (*secdesc_ctr)->sd->dacl,
5493 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5494 if (!new_secdesc_ctr) {
5498 /* Swap with other one */
5500 *secdesc_ctr = new_secdesc_ctr;
5504 nt_printing_setsec(sharename, *secdesc_ctr);
5508 if (DEBUGLEVEL >= 10) {
5509 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
5512 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5513 sharename, the_acl->num_aces));
5515 for (i = 0; i < the_acl->num_aces; i++) {
5516 DEBUG(10, ("%s %d %d 0x%08x\n",
5517 sid_string_dbg(&the_acl->aces[i].trustee),
5518 the_acl->aces[i].type, the_acl->aces[i].flags,
5519 the_acl->aces[i].access_mask));
5528 1: level not implemented
5529 2: file doesn't exist
5530 3: can't allocate memory
5531 4: can't free memory
5532 5: non existant struct
5536 A printer and a printer driver are 2 different things.
5537 NT manages them separatelly, Samba does the same.
5538 Why ? Simply because it's easier and it makes sense !
5540 Now explanation: You have 3 printers behind your samba server,
5541 2 of them are the same make and model (laser A and B). But laser B
5542 has an 3000 sheet feeder and laser A doesn't such an option.
5543 Your third printer is an old dot-matrix model for the accounting :-).
5545 If the /usr/local/samba/lib directory (default dir), you will have
5546 5 files to describe all of this.
5548 3 files for the printers (1 by printer):
5551 NTprinter_accounting
5552 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5553 NTdriver_printer model X
5554 NTdriver_printer model Y
5556 jfm: I should use this comment for the text file to explain
5557 same thing for the forms BTW.
5558 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5562 /* Convert generic access rights to printer object specific access rights.
5563 It turns out that NT4 security descriptors use generic access rights and
5564 NT5 the object specific ones. */
5566 void map_printer_permissions(struct security_descriptor *sd)
5570 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5571 se_map_generic(&sd->dacl->aces[i].access_mask,
5572 &printer_generic_mapping);
5576 void map_job_permissions(struct security_descriptor *sd)
5580 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5581 se_map_generic(&sd->dacl->aces[i].access_mask,
5582 &job_generic_mapping);
5587 /****************************************************************************
5588 Check a user has permissions to perform the given operation. We use the
5589 permission constants defined in include/rpc_spoolss.h to check the various
5590 actions we perform when checking printer access.
5592 PRINTER_ACCESS_ADMINISTER:
5593 print_queue_pause, print_queue_resume, update_printer_sec,
5594 update_printer, spoolss_addprinterex_level_2,
5595 _spoolss_setprinterdata
5600 JOB_ACCESS_ADMINISTER:
5601 print_job_delete, print_job_pause, print_job_resume,
5604 Try access control in the following order (for performance reasons):
5605 1) root and SE_PRINT_OPERATOR can do anything (easy check)
5606 2) check security descriptor (bit comparisons in memory)
5607 3) "printer admins" (may result in numerous calls to winbind)
5609 ****************************************************************************/
5610 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5613 struct sec_desc_buf *secdesc = NULL;
5614 uint32 access_granted;
5617 TALLOC_CTX *mem_ctx = NULL;
5618 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5620 /* If user is NULL then use the current_user structure */
5622 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5624 if (server_info->utok.uid == sec_initial_uid()
5625 || user_has_privileges(server_info->ptok, &se_printop ) ) {
5629 /* Get printer name */
5631 pname = lp_printername(snum);
5633 if (!pname || !*pname) {
5638 /* Get printer security descriptor */
5640 if(!(mem_ctx = talloc_init("print_access_check"))) {
5645 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5646 talloc_destroy(mem_ctx);
5651 if (access_type == JOB_ACCESS_ADMINISTER) {
5652 struct sec_desc_buf *parent_secdesc = secdesc;
5654 /* Create a child security descriptor to check permissions
5655 against. This is because print jobs are child objects
5656 objects of a printer. */
5658 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5660 if (!NT_STATUS_IS_OK(status)) {
5661 talloc_destroy(mem_ctx);
5662 errno = map_errno_from_nt_status(status);
5666 map_job_permissions(secdesc->sd);
5668 map_printer_permissions(secdesc->sd);
5672 status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5675 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5677 /* see if we need to try the printer admin list */
5679 if (!NT_STATUS_IS_OK(status) &&
5680 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5681 NULL, NULL, server_info->ptok,
5682 lp_printer_admin(snum)))) {
5683 talloc_destroy(mem_ctx);
5687 talloc_destroy(mem_ctx);
5689 if (!NT_STATUS_IS_OK(status)) {
5693 return NT_STATUS_IS_OK(status);
5696 /****************************************************************************
5697 Check the time parameters allow a print operation.
5698 *****************************************************************************/
5700 bool print_time_access_check(const char *servicename)
5702 NT_PRINTER_INFO_LEVEL *printer = NULL;
5704 time_t now = time(NULL);
5708 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5711 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5715 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5717 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5720 free_a_printer(&printer, 2);
5728 /****************************************************************************
5729 Fill in the servername sent in the _spoolss_open_printer_ex() call
5730 ****************************************************************************/
5732 char* get_server_name( Printer_entry *printer )
5734 return printer->servername;