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(struct spoolss_DeviceMode *devmode, uint8 *buf, int buflen)
2294 enum ndr_err_code ndr_err;
2299 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
2301 (ndr_push_flags_fn_t)
2302 ndr_push_spoolss_DeviceMode);
2303 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2304 DEBUG(10, ("pack_devicemode: "
2305 "error encoding spoolss_DeviceMode\n"));
2312 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
2315 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
2322 /****************************************************************************
2323 ****************************************************************************/
2324 int unpack_devicemode(TALLOC_CTX *mem_ctx,
2325 const uint8 *buf, int buflen,
2326 struct spoolss_DeviceMode **devmode)
2328 struct spoolss_DeviceMode *dm;
2329 enum ndr_err_code ndr_err;
2337 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
2342 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2347 blob = data_blob_const(data, data_len);
2349 ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
2350 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
2351 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2352 DEBUG(10, ("unpack_devicemode: "
2353 "error parsing spoolss_DeviceMode\n"));
2357 DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
2358 dm->devicename, dm->formname));
2359 if (dm->driverextra_data.data) {
2360 DEBUG(8, ("with a private section of %d bytes\n",
2361 dm->__driverextra_length));
2371 /****************************************************************************
2372 Pack all values in all printer keys
2373 ***************************************************************************/
2375 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2379 struct regval_blob *val;
2380 struct regval_ctr *val_ctr;
2387 /* loop over all keys */
2389 for ( i=0; i<data->num_keys; i++ ) {
2390 val_ctr = data->keys[i].values;
2391 num_values = regval_ctr_numvals( val_ctr );
2393 /* pack the keyname followed by a empty value */
2395 len += tdb_pack(buf+len, buflen-len, "pPdB",
2396 &data->keys[i].name,
2402 /* now loop over all values */
2404 for ( j=0; j<num_values; j++ ) {
2405 /* pathname should be stored as <key>\<value> */
2407 val = regval_ctr_specific_value( val_ctr, j );
2408 if (asprintf(&path, "%s\\%s",
2410 regval_name(val)) < 0) {
2414 len += tdb_pack(buf+len, buflen-len, "pPdB",
2419 regval_data_p(val) );
2421 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2429 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2435 /****************************************************************************
2436 Delete a printer - this just deletes the printer info file, any open
2437 handles are not affected.
2438 ****************************************************************************/
2440 uint32 del_a_printer(const char *sharename)
2443 char *printdb_path = NULL;
2444 TALLOC_CTX *ctx = talloc_tos();
2446 kbuf = make_printer_tdbkey(ctx, sharename);
2447 tdb_delete(tdb_printers, kbuf);
2449 kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2450 tdb_delete(tdb_printers, kbuf);
2452 close_all_print_db();
2454 if (geteuid() == sec_initial_uid()) {
2455 if (asprintf(&printdb_path, "%s%s.tdb",
2456 cache_path("printing/"),
2460 unlink(printdb_path);
2461 SAFE_FREE(printdb_path);
2467 /****************************************************************************
2468 ****************************************************************************/
2469 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2475 TDB_DATA kbuf, dbuf;
2478 * in addprinter: no servername and the printer is the name
2479 * in setprinter: servername is \\server
2480 * and printer is \\server\\printer
2482 * Samba manages only local printers.
2483 * we currently don't support things like i
2484 * path=\\other_server\printer
2486 * We only store the printername, not \\server\printername
2489 if ( info->servername[0] != '\0' ) {
2490 trim_string(info->printername, info->servername, NULL);
2491 trim_char(info->printername, '\\', '\0');
2492 info->servername[0]='\0';
2496 * JFM: one day I'll forget.
2497 * below that's info->portname because that's the SAMBA sharename
2498 * and I made NT 'thinks' it's the portname
2499 * the info->sharename is the thing you can name when you add a printer
2500 * that's the short-name when you create shared printer for 95/98
2501 * So I've made a limitation in SAMBA: you can only have 1 printer model
2502 * behind a SAMBA share.
2510 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2513 info->default_priority,
2530 info->printprocessor,
2534 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2535 retlen = pack_values( info->data, buf+len, buflen-len );
2542 if (buflen != len) {
2543 buf = (uint8 *)SMB_REALLOC(buf, len);
2545 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2553 kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2558 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2561 if (!W_ERROR_IS_OK(ret))
2562 DEBUG(8, ("error updating printer to tdb on disk\n"));
2566 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2567 info->sharename, info->drivername, info->portname, len));
2572 /****************************************************************************
2573 Create and allocate a default devicemode.
2574 ****************************************************************************/
2576 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
2577 const char *devicename,
2578 struct spoolss_DeviceMode **devmode)
2580 struct spoolss_DeviceMode *dm;
2583 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2588 dname = talloc_asprintf(dm, "%s", devicename);
2589 if (dname == NULL) {
2592 if (strlen(dname) > MAXDEVICENAME) {
2593 dname[MAXDEVICENAME] = '\0';
2595 dm->devicename = dname;
2597 dm->formname = talloc_strdup(dm, "Letter");
2598 if (dm->formname == NULL) {
2602 dm->specversion = DMSPEC_NT4_AND_ABOVE;
2603 dm->driverversion = 0x0400;
2605 dm->__driverextra_length = 0;
2606 dm->fields = DEVMODE_FORMNAME |
2608 DEVMODE_PRINTQUALITY |
2609 DEVMODE_DEFAULTSOURCE |
2613 DEVMODE_ORIENTATION;
2614 dm->orientation = DMORIENT_PORTRAIT;
2615 dm->papersize = DMPAPER_LETTER;
2616 dm->paperlength = 0;
2620 dm->defaultsource = DMBIN_FORMSOURCE;
2621 dm->printquality = DMRES_HIGH; /* 0x0258 */
2622 dm->color = DMRES_MONOCHROME;
2623 dm->duplex = DMDUP_SIMPLEX;
2624 dm->yresolution = 0;
2625 dm->ttoption = DMTT_SUBDEV;
2626 dm->collate = DMCOLLATE_FALSE;
2636 dm->displayflags = 0;
2637 dm->displayfrequency = 0;
2640 dm->panningwidth = 0;
2641 dm->panningheight = 0;
2643 dm->driverextra_data.data = NULL;
2644 dm->driverextra_data.length = 0;
2650 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
2651 struct spoolss_security_descriptor **secdesc)
2653 struct security_ace ace[7]; /* max number of ace entries */
2656 struct security_acl *psa = NULL;
2657 struct security_descriptor *psd = NULL;
2658 struct dom_sid adm_sid;
2661 /* Create an ACE where Everyone is allowed to print */
2663 sa = PRINTER_ACE_PRINT;
2664 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2665 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2667 /* Add the domain admins group if we are a DC */
2670 struct dom_sid domadmins_sid;
2672 sid_compose(&domadmins_sid, get_global_sam_sid(),
2675 sa = PRINTER_ACE_FULL_CONTROL;
2676 init_sec_ace(&ace[i++], &domadmins_sid,
2677 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2678 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2679 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2680 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2682 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
2683 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
2685 sa = PRINTER_ACE_FULL_CONTROL;
2686 init_sec_ace(&ace[i++], &adm_sid,
2687 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2688 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2689 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2690 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2693 /* add BUILTIN\Administrators as FULL CONTROL */
2695 sa = PRINTER_ACE_FULL_CONTROL;
2696 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2697 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2698 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2699 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2700 SEC_ACE_TYPE_ACCESS_ALLOWED,
2701 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2703 /* add BUILTIN\Print Operators as FULL CONTROL */
2705 sa = PRINTER_ACE_FULL_CONTROL;
2706 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2707 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2708 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2709 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2710 SEC_ACE_TYPE_ACCESS_ALLOWED,
2711 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2713 /* Make the security descriptor owned by the BUILTIN\Administrators */
2715 /* The ACL revision number in rpc_secdesc.h differs from the one
2716 created by NT when setting ACE entries in printer
2717 descriptors. NT4 complains about the property being edited by a
2720 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
2721 psd = make_sec_desc(mem_ctx,
2723 SEC_DESC_SELF_RELATIVE,
2724 &global_sid_Builtin_Administrators,
2725 &global_sid_Builtin_Administrators,
2732 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2736 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2737 (unsigned int)sd_size));
2744 /****************************************************************************
2745 Allocate and initialize a new slot.
2746 ***************************************************************************/
2748 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2754 if ( !name || !data )
2757 /* allocate another slot in the NT_PRINTER_KEY array */
2759 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2760 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2766 key_index = data->num_keys;
2768 /* initialze new key */
2770 data->keys[key_index].name = talloc_strdup( data, name );
2772 werr = regval_ctr_init(data, &(data->keys[key_index].values));
2773 if (!W_ERROR_IS_OK(werr)) {
2779 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2784 /****************************************************************************
2785 search for a registry key name in the existing printer data
2786 ***************************************************************************/
2788 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2792 for ( i=0; i<data->num_keys; i++ ) {
2793 if ( strequal( data->keys[i].name, name ) ) {
2795 /* cleanup memory */
2797 TALLOC_FREE( data->keys[i].name );
2798 TALLOC_FREE( data->keys[i].values );
2800 /* if not the end of the array, move remaining elements down one slot */
2803 if ( data->num_keys && (i < data->num_keys) )
2804 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2811 return data->num_keys;
2814 /****************************************************************************
2815 search for a registry key name in the existing printer data
2816 ***************************************************************************/
2818 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2823 if ( !data || !name )
2826 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2828 /* loop over all existing keys */
2830 for ( i=0; i<data->num_keys; i++ ) {
2831 if ( strequal(data->keys[i].name, name) ) {
2832 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2842 /****************************************************************************
2843 ***************************************************************************/
2845 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2849 int num_subkeys = 0;
2851 fstring *subkeys_ptr = NULL;
2862 /* special case of asking for the top level printer data registry key names */
2864 if ( strlen(key) == 0 ) {
2865 for ( i=0; i<data->num_keys; i++ ) {
2867 /* found a match, so allocate space and copy the name */
2869 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2870 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2875 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2882 /* asking for the subkeys of some key */
2883 /* subkey paths are stored in the key name using '\' as the delimiter */
2885 for ( i=0; i<data->num_keys; i++ ) {
2886 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2888 /* if we found the exact key, then break */
2889 key_len = strlen( key );
2890 if ( strlen(data->keys[i].name) == key_len )
2893 /* get subkey path */
2895 p = data->keys[i].name + key_len;
2898 fstrcpy( subkeyname, p );
2899 if ( (p = strchr( subkeyname, '\\' )) )
2902 /* don't add a key more than once */
2904 for ( j=0; j<num_subkeys; j++ ) {
2905 if ( strequal( subkeys_ptr[j], subkeyname ) )
2909 if ( j != num_subkeys )
2912 /* found a match, so allocate space and copy the name */
2914 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2915 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2920 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2926 /* return error if the key was not found */
2928 if ( i == data->num_keys ) {
2929 SAFE_FREE(subkeys_ptr);
2934 /* tag off the end */
2937 fstrcpy(subkeys_ptr[num_subkeys], "" );
2939 *subkeys = subkeys_ptr;
2945 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
2948 regval_ctr_delvalue(ctr, val_name);
2949 regval_ctr_addvalue_sz(ctr, val_name, sz);
2952 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
2955 regval_ctr_delvalue(ctr, val_name);
2956 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2957 (uint8 *) &dword, sizeof(dword));
2960 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
2963 uint8 bin_bool = (b ? 1 : 0);
2964 regval_ctr_delvalue(ctr, val_name);
2965 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2966 (uint8 *) &bin_bool, sizeof(bin_bool));
2969 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
2970 const char *multi_sz)
2977 regval_ctr_delvalue(ctr, val_name);
2978 regval_ctr_addvalue_multi_sz(ctr, val_name, a);
2981 /****************************************************************************
2982 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2984 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2985 * @return bool indicating success or failure
2986 ***************************************************************************/
2988 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2990 struct regval_ctr *ctr = NULL;
2992 const char *dnssuffix;
2993 char *allocated_string = NULL;
2994 const char *ascii_str;
2997 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2998 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2999 ctr = info2->data->keys[i].values;
3001 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3002 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3004 /* we make the assumption that the netbios name is the same
3005 as the DNS name sinc ethe former will be what we used to
3008 dnssuffix = get_mydnsdomname(talloc_tos());
3009 if (dnssuffix && *dnssuffix) {
3010 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3012 fstrcpy( longname, global_myname() );
3015 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3017 if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3020 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3021 SAFE_FREE(allocated_string);
3023 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3024 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3025 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3026 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3027 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3028 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3029 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3030 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3031 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3033 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3034 (info2->attributes &
3035 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3037 switch (info2->attributes & 0x3) {
3039 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3042 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3045 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3048 ascii_str = "unknown";
3050 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3055 /*****************************************************************
3056 ****************************************************************/
3058 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3062 struct regval_ctr *ctr=NULL;
3064 /* find the DsSpooler key */
3065 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3066 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3067 ctr = info2->data->keys[i].values;
3069 regval_ctr_delvalue(ctr, "objectGUID");
3071 /* We used to store this as a REG_BINARY but that causes
3074 regval_ctr_addvalue_sz(ctr, "objectGUID",
3075 GUID_string(talloc_tos(), &guid));
3078 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3079 NT_PRINTER_INFO_LEVEL *printer)
3083 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3084 char *srv_dn_utf8, **srv_cn_utf8;
3087 const char *attrs[] = {"objectGUID", NULL};
3089 WERROR win_rc = WERR_OK;
3090 size_t converted_size;
3092 /* build the ads mods */
3093 ctx = talloc_init("nt_printer_publish_ads");
3098 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3100 /* figure out where to publish */
3101 ads_find_machine_acct(ads, &res, global_myname());
3103 /* We use ldap_get_dn here as we need the answer
3104 * in utf8 to call ldap_explode_dn(). JRA. */
3106 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3109 return WERR_SERVER_UNAVAILABLE;
3111 ads_msgfree(ads, res);
3112 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3115 ldap_memfree(srv_dn_utf8);
3116 return WERR_SERVER_UNAVAILABLE;
3118 /* Now convert to CH_UNIX. */
3119 if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3121 ldap_memfree(srv_dn_utf8);
3122 ldap_memfree(srv_cn_utf8);
3123 return WERR_SERVER_UNAVAILABLE;
3125 if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3127 ldap_memfree(srv_dn_utf8);
3128 ldap_memfree(srv_cn_utf8);
3129 TALLOC_FREE(srv_dn);
3130 return WERR_SERVER_UNAVAILABLE;
3133 ldap_memfree(srv_dn_utf8);
3134 ldap_memfree(srv_cn_utf8);
3136 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3137 if (!srv_cn_escaped) {
3139 return WERR_SERVER_UNAVAILABLE;
3141 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3142 if (!sharename_escaped) {
3143 SAFE_FREE(srv_cn_escaped);
3145 return WERR_SERVER_UNAVAILABLE;
3148 prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3150 SAFE_FREE(srv_cn_escaped);
3151 SAFE_FREE(sharename_escaped);
3153 mods = ads_init_mods(ctx);
3161 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3162 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3163 printer->info_2->sharename);
3166 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3167 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3169 for (i=0; mods[i] != 0; i++)
3171 mods[i] = (LDAPMod *)-1;
3172 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3175 if (!ADS_ERR_OK(ads_rc))
3176 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3178 /* retreive the guid and store it locally */
3179 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3181 ads_pull_guid(ads, res, &guid);
3182 ads_msgfree(ads, res);
3183 store_printer_guid(printer->info_2, guid);
3184 win_rc = mod_a_printer(printer, 2);
3191 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3192 NT_PRINTER_INFO_LEVEL *printer)
3195 LDAPMessage *res = NULL;
3196 char *prt_dn = NULL;
3198 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3200 /* remove the printer from the directory */
3201 ads_rc = ads_find_printer_on_server(ads, &res,
3202 printer->info_2->sharename, global_myname());
3204 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3205 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3207 ads_msgfree(ads, res);
3210 ads_rc = ads_del_dn(ads, prt_dn);
3211 TALLOC_FREE(prt_dn);
3215 ads_msgfree(ads, res);
3220 /****************************************************************************
3221 * Publish a printer in the directory
3223 * @param snum describing printer service
3224 * @return WERROR indicating status of publishing
3225 ***************************************************************************/
3227 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3230 ADS_STRUCT *ads = NULL;
3231 NT_PRINTER_INFO_LEVEL *printer = NULL;
3234 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3235 if (!W_ERROR_IS_OK(win_rc))
3239 case DSPRINT_PUBLISH:
3240 case DSPRINT_UPDATE:
3241 /* set the DsSpooler info and attributes */
3242 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3243 win_rc = WERR_NOMEM;
3247 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3249 case DSPRINT_UNPUBLISH:
3250 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3253 win_rc = WERR_NOT_SUPPORTED;
3257 win_rc = mod_a_printer(printer, 2);
3258 if (!W_ERROR_IS_OK(win_rc)) {
3259 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3263 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3265 DEBUG(3, ("ads_init() failed\n"));
3266 win_rc = WERR_SERVER_UNAVAILABLE;
3269 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3270 SAFE_FREE(ads->auth.password);
3271 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3274 /* ads_connect() will find the DC for us */
3275 ads_rc = ads_connect(ads);
3276 if (!ADS_ERR_OK(ads_rc)) {
3277 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3278 win_rc = WERR_ACCESS_DENIED;
3283 case DSPRINT_PUBLISH:
3284 case DSPRINT_UPDATE:
3285 win_rc = nt_printer_publish_ads(ads, printer);
3287 case DSPRINT_UNPUBLISH:
3288 win_rc = nt_printer_unpublish_ads(ads, printer);
3293 free_a_printer(&printer, 2);
3298 WERROR check_published_printers(void)
3301 ADS_STRUCT *ads = NULL;
3303 int n_services = lp_numservices();
3304 NT_PRINTER_INFO_LEVEL *printer = NULL;
3306 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3308 DEBUG(3, ("ads_init() failed\n"));
3309 return WERR_SERVER_UNAVAILABLE;
3311 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3312 SAFE_FREE(ads->auth.password);
3313 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3316 /* ads_connect() will find the DC for us */
3317 ads_rc = ads_connect(ads);
3318 if (!ADS_ERR_OK(ads_rc)) {
3319 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3321 ads_kdestroy("MEMORY:prtpub_cache");
3322 return WERR_ACCESS_DENIED;
3325 for (snum = 0; snum < n_services; snum++) {
3326 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3329 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3330 lp_servicename(snum))) &&
3331 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3332 nt_printer_publish_ads(ads, printer);
3334 free_a_printer(&printer, 2);
3338 ads_kdestroy("MEMORY:prtpub_cache");
3342 bool is_printer_published(Printer_entry *print_hnd, int snum,
3345 NT_PRINTER_INFO_LEVEL *printer = NULL;
3346 struct regval_ctr *ctr;
3347 struct regval_blob *guid_val;
3353 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3355 if (!W_ERROR_IS_OK(win_rc) ||
3356 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3357 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3358 !(ctr = printer->info_2->data->keys[i].values) ||
3359 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3361 free_a_printer(&printer, 2);
3365 /* fetching printer guids really ought to be a separate function. */
3370 /* We used to store the guid as REG_BINARY, then swapped
3371 to REG_SZ for Vista compatibility so check for both */
3373 switch ( regval_type(guid_val) ){
3375 blob = data_blob_const(regval_data_p(guid_val),
3376 regval_size(guid_val));
3377 pull_reg_sz(talloc_tos(), &blob, (const char **)&guid_str);
3378 ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3379 talloc_free(guid_str);
3382 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3386 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3389 DEBUG(0,("is_printer_published: GUID value stored as "
3390 "invaluid type (%d)\n", regval_type(guid_val) ));
3395 free_a_printer(&printer, 2);
3399 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3404 WERROR check_published_printers(void)
3409 bool is_printer_published(Printer_entry *print_hnd, int snum,
3414 #endif /* HAVE_ADS */
3416 /****************************************************************************
3417 ***************************************************************************/
3419 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3421 NT_PRINTER_DATA *data;
3423 int removed_keys = 0;
3427 empty_slot = data->num_keys;
3430 return WERR_INVALID_PARAM;
3432 /* remove all keys */
3434 if ( !strlen(key) ) {
3436 TALLOC_FREE( data );
3440 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3446 /* remove a specific key (and all subkeys) */
3448 for ( i=0; i<data->num_keys; i++ ) {
3449 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3450 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3451 data->keys[i].name));
3453 TALLOC_FREE( data->keys[i].name );
3454 TALLOC_FREE( data->keys[i].values );
3456 /* mark the slot as empty */
3458 ZERO_STRUCTP( &data->keys[i] );
3462 /* find the first empty slot */
3464 for ( i=0; i<data->num_keys; i++ ) {
3465 if ( !data->keys[i].name ) {
3472 if ( i == data->num_keys )
3473 /* nothing was removed */
3474 return WERR_INVALID_PARAM;
3476 /* move everything down */
3478 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3479 if ( data->keys[i].name ) {
3480 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3481 ZERO_STRUCTP( &data->keys[i] );
3489 data->num_keys -= removed_keys;
3491 /* sanity check to see if anything is left */
3493 if ( !data->num_keys ) {
3494 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3496 SAFE_FREE( data->keys );
3497 ZERO_STRUCTP( data );
3503 /****************************************************************************
3504 ***************************************************************************/
3506 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3508 WERROR result = WERR_OK;
3511 /* we must have names on non-zero length */
3513 if ( !key || !*key|| !value || !*value )
3514 return WERR_INVALID_NAME;
3516 /* find the printer key first */
3518 key_index = lookup_printerkey( p2->data, key );
3519 if ( key_index == -1 )
3522 /* make sure the value exists so we can return the correct error code */
3524 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3525 return WERR_BADFILE;
3527 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3529 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3535 /****************************************************************************
3536 ***************************************************************************/
3538 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3539 uint32 type, uint8 *data, int real_len )
3541 WERROR result = WERR_OK;
3544 /* we must have names on non-zero length */
3546 if ( !key || !*key|| !value || !*value )
3547 return WERR_INVALID_NAME;
3549 /* find the printer key first */
3551 key_index = lookup_printerkey( p2->data, key );
3552 if ( key_index == -1 )
3553 key_index = add_new_printer_key( p2->data, key );
3555 if ( key_index == -1 )
3558 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3559 type, data, real_len );
3561 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3562 key, value, type, real_len ));
3567 /****************************************************************************
3568 ***************************************************************************/
3570 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3574 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3577 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3580 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3583 /****************************************************************************
3584 Unpack a list of registry values frem the TDB
3585 ***************************************************************************/
3587 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3592 const char *valuename = NULL;
3593 const char *keyname = NULL;
3597 struct regval_blob *regval_p;
3600 /* add the "PrinterDriverData" key first for performance reasons */
3602 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3604 /* loop and unpack the rest of the registry values */
3608 /* check to see if there are any more registry values */
3611 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3615 /* unpack the next regval */
3617 len += tdb_unpack(buf+len, buflen-len, "fdB",
3623 /* lookup for subkey names which have a type of REG_NONE */
3624 /* there's no data with this entry */
3626 if ( type == REG_NONE ) {
3627 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3628 add_new_printer_key( printer_data, string );
3633 * break of the keyname from the value name.
3634 * Valuenames can have embedded '\'s so be careful.
3635 * only support one level of keys. See the
3636 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3640 str = strchr_m( string, '\\');
3642 /* Put in "PrinterDriverData" is no key specified */
3645 keyname = SPOOL_PRINTERDATA_KEY;
3654 /* see if we need a new key */
3656 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3657 key_index = add_new_printer_key( printer_data, keyname );
3659 if ( key_index == -1 ) {
3660 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3665 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3667 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3668 Thanks to Martin Zielinski for the hint. */
3670 if ( type == REG_BINARY &&
3671 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3672 strequal( valuename, "objectGUID" ) )
3676 /* convert the GUID to a UNICODE string */
3678 memcpy( &guid, data_p, sizeof(struct GUID) );
3680 regval_ctr_addvalue_sz(printer_data->keys[key_index].values,
3682 GUID_string(talloc_tos(), &guid));
3687 regval_ctr_addvalue( printer_data->keys[key_index].values,
3688 valuename, type, data_p,
3692 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3699 /****************************************************************************
3700 ***************************************************************************/
3702 static char *win_driver;
3703 static char *os2_driver;
3705 static const char *get_win_driver(void)
3707 if (win_driver == NULL) {
3713 static const char *get_os2_driver(void)
3715 if (os2_driver == NULL) {
3721 static bool set_driver_mapping(const char *from, const char *to)
3723 SAFE_FREE(win_driver);
3724 SAFE_FREE(os2_driver);
3726 win_driver = SMB_STRDUP(from);
3727 os2_driver = SMB_STRDUP(to);
3729 if (win_driver == NULL || os2_driver == NULL) {
3730 SAFE_FREE(win_driver);
3731 SAFE_FREE(os2_driver);
3737 static void map_to_os2_driver(fstring drivername)
3739 char *mapfile = lp_os2_driver_map();
3740 char **lines = NULL;
3744 if (!strlen(drivername))
3750 if (strequal(drivername, get_win_driver())) {
3751 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3752 drivername, get_os2_driver()));
3753 fstrcpy(drivername, get_os2_driver());
3757 lines = file_lines_load(mapfile, &numlines,0,NULL);
3758 if (numlines == 0 || lines == NULL) {
3759 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3764 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3766 for( i = 0; i < numlines; i++) {
3767 char *nt_name = lines[i];
3768 char *os2_name = strchr(nt_name,'=');
3775 while (isspace(*nt_name))
3778 if (!*nt_name || strchr("#;",*nt_name))
3782 int l = strlen(nt_name);
3783 while (l && isspace(nt_name[l-1])) {
3789 while (isspace(*os2_name))
3793 int l = strlen(os2_name);
3794 while (l && isspace(os2_name[l-1])) {
3800 if (strequal(nt_name,drivername)) {
3801 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3802 set_driver_mapping(drivername,os2_name);
3803 fstrcpy(drivername,os2_name);
3815 * @brief Map a Windows driver to a OS/2 driver.
3817 * @param[in] mem_ctx The memory context to use.
3819 * @param[in,out] pdrivername The drivername of Windows to remap.
3821 * @return WERR_OK on success, a corresponding WERROR on failure.
3823 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
3825 const char *mapfile = lp_os2_driver_map();
3826 char **lines = NULL;
3827 const char *drivername;
3831 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
3832 return WERR_INVALID_PARAMETER;
3835 drivername = *pdrivername;
3837 if (mapfile[0] == '\0') {
3838 return WERR_BADFILE;
3841 if (strequal(drivername, get_win_driver())) {
3842 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3843 drivername, get_os2_driver()));
3844 drivername = talloc_strdup(mem_ctx, get_os2_driver());
3845 if (drivername == NULL) {
3848 *pdrivername = drivername;
3852 lines = file_lines_load(mapfile, &numlines, 0, NULL);
3853 if (numlines == 0 || lines == NULL) {
3854 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
3859 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3861 for( i = 0; i < numlines; i++) {
3862 char *nt_name = lines[i];
3863 char *os2_name = strchr(nt_name, '=');
3865 if (os2_name == NULL) {
3871 while (isspace(*nt_name)) {
3875 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
3880 int l = strlen(nt_name);
3881 while (l && isspace(nt_name[l - 1])) {
3887 while (isspace(*os2_name)) {
3892 int l = strlen(os2_name);
3893 while (l && isspace(os2_name[l-1])) {
3899 if (strequal(nt_name, drivername)) {
3900 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
3901 set_driver_mapping(drivername, os2_name);
3902 drivername = talloc_strdup(mem_ctx, os2_name);
3904 if (drivername == NULL) {
3907 *pdrivername = drivername;
3916 /****************************************************************************
3917 Get a default printer info 2 struct.
3918 ****************************************************************************/
3920 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
3921 const char *servername,
3922 const char* sharename,
3925 int snum = lp_servicenumber(sharename);
3928 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3929 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3930 servername, sharename);
3931 fstrcpy(info->sharename, sharename);
3932 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3934 /* by setting the driver name to an empty string, a local NT admin
3935 can now run the **local** APW to install a local printer driver
3936 for a Samba shared printer in 2.2. Without this, drivers **must** be
3937 installed on the Samba server for NT clients --jerry */
3938 #if 0 /* JERRY --do not uncomment-- */
3939 if (!*info->drivername)
3940 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3944 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3946 strlcpy(info->comment, "", sizeof(info->comment));
3947 fstrcpy(info->printprocessor, "winprint");
3948 fstrcpy(info->datatype, "RAW");
3951 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3952 /* Pull the location and comment strings from cups if we don't
3954 if ( !strlen(info->location) || !strlen(info->comment) ) {
3955 char *comment = NULL;
3956 char *location = NULL;
3957 if (cups_pull_comment_location(info, info->sharename,
3958 &comment, &location)) {
3959 strlcpy(info->comment, comment, sizeof(info->comment));
3960 fstrcpy(info->location, location);
3961 TALLOC_FREE(comment);
3962 TALLOC_FREE(location);
3968 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3970 info->starttime = 0; /* Minutes since 12:00am GMT */
3971 info->untiltime = 0; /* Minutes since 12:00am GMT */
3973 info->default_priority = 1;
3974 info->setuptime = (uint32)time(NULL);
3977 * I changed this as I think it is better to have a generic
3978 * DEVMODE than to crash Win2k explorer.exe --jerry
3979 * See the HP Deskjet 990c Win2k drivers for an example.
3981 * However the default devmode appears to cause problems
3982 * with the HP CLJ 8500 PCL driver. Hence the addition of
3983 * the "default devmode" parameter --jerry 22/01/2002
3986 if (lp_default_devmode(snum)) {
3987 result = spoolss_create_default_devmode(info,
3990 if (!W_ERROR_IS_OK(result)) {
3994 info->devmode = NULL;
3997 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4001 info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
4006 add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
4011 TALLOC_FREE(info->devmode);
4013 return WERR_ACCESS_DENIED;
4016 /****************************************************************************
4017 ****************************************************************************/
4019 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
4020 const char *servername,
4021 const char *sharename,
4025 int snum = lp_servicenumber(sharename);
4026 TDB_DATA kbuf, dbuf;
4027 fstring printername;
4028 char *comment = NULL;
4031 kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4033 dbuf = tdb_fetch(tdb_printers, kbuf);
4035 return get_a_printer_2_default(info, servername,
4036 sharename, get_loc_com);
4039 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4042 &info->default_priority,
4049 &info->c_setprinter,
4059 info->printprocessor,
4064 strlcpy(info->comment, comment, sizeof(info->comment));
4068 /* Samba has to have shared raw drivers. */
4069 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4070 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4072 /* Restore the stripped strings. */
4073 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4075 if ( lp_force_printername(snum) ) {
4076 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4078 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4081 fstrcpy(info->printername, printername);
4084 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4085 /* Pull the location and comment strings from cups if we don't
4087 if ( !strlen(info->location) || !strlen(info->comment) ) {
4088 char *location = NULL;
4090 if (cups_pull_comment_location(info, info->sharename,
4091 &comment, &location)) {
4092 strlcpy(info->comment, comment, sizeof(info->comment));
4093 fstrcpy(info->location, location);
4094 TALLOC_FREE(comment);
4095 TALLOC_FREE(location);
4101 len += unpack_devicemode(info, dbuf.dptr+len,
4106 * Some client drivers freak out if there is a NULL devmode
4107 * (probably the driver is not checking before accessing
4108 * the devmode pointer) --jerry
4110 * See comments in get_a_printer_2_default()
4113 if (lp_default_devmode(snum) && !info->devmode) {
4114 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4116 result = spoolss_create_default_devmode(info, printername,
4118 if (!W_ERROR_IS_OK(result)) {
4123 if (info->devmode) {
4124 info->devmode->devicename = talloc_strdup(info->devmode,
4126 if (!info->devmode->devicename) {
4127 result = WERR_NOMEM;
4132 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4133 DEBUG(0,("unpack_values: talloc() failed!\n"));
4134 result = WERR_NOMEM;
4137 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4139 /* This will get the current RPC talloc context, but we should be
4140 passing this as a parameter... fixme... JRA ! */
4142 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4143 result = WERR_NOMEM;
4147 /* Fix for OS/2 drivers. */
4149 if (get_remote_arch() == RA_OS2) {
4150 map_to_os2_driver(info->drivername);
4153 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4154 sharename, info->printername, info->drivername));
4159 SAFE_FREE(dbuf.dptr);
4163 /****************************************************************************
4164 Debugging function, dump at level 6 the struct in the logs.
4165 ****************************************************************************/
4166 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4169 NT_PRINTER_INFO_LEVEL_2 *info2;
4171 DEBUG(106,("Dumping printer at level [%d]\n", level));
4176 if (printer->info_2 == NULL)
4180 info2=printer->info_2;
4182 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4183 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4184 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4185 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4186 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4187 DEBUGADD(106,("status:[%d]\n", info2->status));
4188 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4189 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4190 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4191 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4192 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4194 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4195 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4196 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4197 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4198 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4199 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4200 DEBUGADD(106,("location:[%s]\n", info2->location));
4201 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4202 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4203 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4204 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4210 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4218 /****************************************************************************
4219 Update the changeid time.
4220 This is SO NASTY as some drivers need this to change, others need it
4221 static. This value will change every second, and I must hope that this
4222 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4224 ****************************************************************************/
4226 static uint32 rev_changeid(void)
4230 get_process_uptime(&tv);
4233 /* Return changeid as msec since spooler restart */
4234 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4237 * This setting seems to work well but is too untested
4238 * to replace the above calculation. Left in for experiementation
4239 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4241 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4247 * The function below are the high level ones.
4248 * only those ones must be called from the spoolss code.
4252 /****************************************************************************
4253 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4254 ****************************************************************************/
4256 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4260 dump_a_printer(printer, level);
4266 * Update the changestamp. Emperical tests show that the
4267 * ChangeID is always updated,but c_setprinter is
4268 * global spooler variable (not per printer).
4271 /* ChangeID **must** be increasing over the lifetime
4272 of client's spoolss service in order for the
4273 client's cache to show updates */
4275 printer->info_2->changeid = rev_changeid();
4278 * Because one day someone will ask:
4279 * NT->NT An admin connection to a remote
4280 * printer show changes imeediately in
4281 * the properities dialog
4283 * A non-admin connection will only show the
4284 * changes after viewing the properites page
4285 * 2 times. Seems to be related to a
4286 * race condition in the client between the spooler
4287 * updating the local cache and the Explorer.exe GUI
4288 * actually displaying the properties.
4290 * This is fixed in Win2k. admin/non-admin
4291 * connections both display changes immediately.
4296 result=update_a_printer_2(printer->info_2);
4300 result=WERR_UNKNOWN_LEVEL;
4307 /****************************************************************************
4308 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4310 Previously the code had a memory allocation problem because it always
4311 used the TALLOC_CTX from the Printer_entry*. This context lasts
4312 as a long as the original handle is open. So if the client made a lot
4313 of getprinter[data]() calls, the memory usage would climb. Now we use
4314 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4315 still use the Printer_entry->ctx for maintaining the cache copy though
4316 since that object must live as long as the handle by definition.
4319 ****************************************************************************/
4321 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4322 const char *sharename, bool get_loc_com)
4327 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4329 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4330 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4336 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4337 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4338 TALLOC_FREE( *pp_printer );
4343 fstrcpy( servername, print_hnd->servername );
4345 fstrcpy( servername, "%L" );
4346 standard_sub_basic( "", "", servername,
4347 sizeof(servername)-1 );
4350 result = get_a_printer_2( (*pp_printer)->info_2,
4351 servername, sharename, get_loc_com);
4353 /* we have a new printer now. Save it with this handle */
4355 if ( !W_ERROR_IS_OK(result) ) {
4356 TALLOC_FREE( *pp_printer );
4357 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4358 sharename, (unsigned int)level, win_errstr(result)));
4362 dump_a_printer( *pp_printer, level);
4367 TALLOC_FREE( *pp_printer );
4368 return WERR_UNKNOWN_LEVEL;
4374 WERROR get_a_printer( Printer_entry *print_hnd,
4375 NT_PRINTER_INFO_LEVEL **pp_printer,
4377 const char *sharename)
4379 return get_a_printer_internal(print_hnd, pp_printer, level,
4383 WERROR get_a_printer_search( Printer_entry *print_hnd,
4384 NT_PRINTER_INFO_LEVEL **pp_printer,
4386 const char *sharename)
4388 return get_a_printer_internal(print_hnd, pp_printer, level,
4392 /****************************************************************************
4393 Deletes a NT_PRINTER_INFO_LEVEL struct.
4394 ****************************************************************************/
4396 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4398 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4405 TALLOC_FREE(printer->info_2);
4409 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4413 TALLOC_FREE(*pp_printer);
4418 /****************************************************************************
4419 ****************************************************************************/
4421 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
4422 struct spoolss_DriverInfo8 *_info8)
4424 struct spoolss_DriverInfo8 info8;
4430 info8.version = r->info.info3->version;
4431 info8.driver_name = r->info.info3->driver_name;
4432 info8.architecture = r->info.info3->architecture;
4433 info8.driver_path = r->info.info3->driver_path;
4434 info8.data_file = r->info.info3->data_file;
4435 info8.config_file = r->info.info3->config_file;
4436 info8.help_file = r->info.info3->help_file;
4437 info8.monitor_name = r->info.info3->monitor_name;
4438 info8.default_datatype = r->info.info3->default_datatype;
4439 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
4440 info8.dependent_files = r->info.info3->dependent_files->string;
4444 info8.version = r->info.info6->version;
4445 info8.driver_name = r->info.info6->driver_name;
4446 info8.architecture = r->info.info6->architecture;
4447 info8.driver_path = r->info.info6->driver_path;
4448 info8.data_file = r->info.info6->data_file;
4449 info8.config_file = r->info.info6->config_file;
4450 info8.help_file = r->info.info6->help_file;
4451 info8.monitor_name = r->info.info6->monitor_name;
4452 info8.default_datatype = r->info.info6->default_datatype;
4453 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
4454 info8.dependent_files = r->info.info6->dependent_files->string;
4456 info8.driver_date = r->info.info6->driver_date;
4457 info8.driver_version = r->info.info6->driver_version;
4458 info8.manufacturer_name = r->info.info6->manufacturer_name;
4459 info8.manufacturer_url = r->info.info6->manufacturer_url;
4460 info8.hardware_id = r->info.info6->hardware_id;
4461 info8.provider = r->info.info6->provider;
4464 info8.version = r->info.info8->version;
4465 info8.driver_name = r->info.info8->driver_name;
4466 info8.architecture = r->info.info8->architecture;
4467 info8.driver_path = r->info.info8->driver_path;
4468 info8.data_file = r->info.info8->data_file;
4469 info8.config_file = r->info.info8->config_file;
4470 info8.help_file = r->info.info8->help_file;
4471 info8.monitor_name = r->info.info8->monitor_name;
4472 info8.default_datatype = r->info.info8->default_datatype;
4473 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
4474 info8.dependent_files = r->info.info8->dependent_files->string;
4476 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
4477 info8.previous_names = r->info.info8->previous_names->string;
4479 info8.driver_date = r->info.info8->driver_date;
4480 info8.driver_version = r->info.info8->driver_version;
4481 info8.manufacturer_name = r->info.info8->manufacturer_name;
4482 info8.manufacturer_url = r->info.info8->manufacturer_url;
4483 info8.hardware_id = r->info.info8->hardware_id;
4484 info8.provider = r->info.info8->provider;
4485 info8.print_processor = r->info.info8->print_processor;
4486 info8.vendor_setup = r->info.info8->vendor_setup;
4487 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
4488 info8.color_profiles = r->info.info8->color_profiles->string;
4490 info8.inf_path = r->info.info8->inf_path;
4491 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
4492 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
4493 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
4495 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
4496 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
4508 uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx,
4509 struct spoolss_AddDriverInfoCtr *r,
4513 struct spoolss_DriverInfo8 info8;
4517 DEBUG(10,("adding a printer at level [%d]\n", r->level));
4519 if (!driver_info_ctr_to_info8(r, &info8)) {
4523 *driver_name = talloc_strdup(mem_ctx, info8.driver_name);
4524 if (!*driver_name) {
4527 *version = info8.version;
4529 return add_a_printer_driver_8(&info8);
4532 /****************************************************************************
4533 ****************************************************************************/
4535 WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx,
4536 struct spoolss_DriverInfo8 **driver,
4537 const char *drivername, const char *architecture,
4541 struct spoolss_DriverInfo3 info3;
4542 struct spoolss_DriverInfo8 *info8;
4546 /* Sometime we just want any version of the driver */
4548 if (version == DRIVER_ANY_VERSION) {
4549 /* look for Win2k first and then for NT4 */
4550 result = get_a_printer_driver_3(mem_ctx,
4554 if (!W_ERROR_IS_OK(result)) {
4555 result = get_a_printer_driver_3(mem_ctx,
4561 result = get_a_printer_driver_3(mem_ctx,
4568 if (!W_ERROR_IS_OK(result)) {
4572 info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8);
4577 info8->version = info3.version;
4578 info8->driver_name = info3.driver_name;
4579 info8->architecture = info3.architecture;
4580 info8->driver_path = info3.driver_path;
4581 info8->data_file = info3.data_file;
4582 info8->config_file = info3.config_file;
4583 info8->help_file = info3.help_file;
4584 info8->dependent_files = info3.dependent_files;
4585 info8->monitor_name = info3.monitor_name;
4586 info8->default_datatype = info3.default_datatype;
4593 /****************************************************************************
4594 ****************************************************************************/
4596 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver)
4598 talloc_free(driver);
4603 /****************************************************************************
4604 Determine whether or not a particular driver is currently assigned
4606 ****************************************************************************/
4608 bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r)
4611 int n_services = lp_numservices();
4612 NT_PRINTER_INFO_LEVEL *printer = NULL;
4613 bool in_use = False;
4619 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4621 /* loop through the printers.tdb and check for the drivername */
4623 for (snum=0; snum<n_services && !in_use; snum++) {
4624 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4627 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4630 if (strequal(r->driver_name, printer->info_2->drivername))
4633 free_a_printer( &printer, 2 );
4636 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4639 struct spoolss_DriverInfo8 *d;
4642 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
4644 /* we can still remove the driver if there is one of
4645 "Windows NT x86" version 2 or 3 left */
4647 if (!strequal("Windows NT x86", r->architecture)) {
4648 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION);
4651 switch (r->version) {
4653 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3);
4656 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2);
4659 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4661 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4666 /* now check the error code */
4668 if ( W_ERROR_IS_OK(werr) ) {
4669 /* it's ok to remove the driver, we have other architctures left */
4671 free_a_printer_driver(d);
4675 /* report that the driver is not in use by default */
4681 /**********************************************************************
4682 Check to see if a ogiven file is in use by *info
4683 *********************************************************************/
4685 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
4692 /* mz: skip files that are in the list but already deleted */
4693 if (!file || !file[0]) {
4697 if (strequal(file, info->driver_path))
4700 if (strequal(file, info->data_file))
4703 if (strequal(file, info->config_file))
4706 if (strequal(file, info->help_file))
4709 /* see of there are any dependent files to examine */
4711 if (!info->dependent_files)
4714 while (info->dependent_files[i] && *info->dependent_files[i]) {
4715 if (strequal(file, info->dependent_files[i]))
4724 /**********************************************************************
4725 Utility function to remove the dependent file pointed to by the
4726 input parameter from the list
4727 *********************************************************************/
4729 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
4732 /* bump everything down a slot */
4734 while (files && files[idx+1]) {
4735 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
4744 /**********************************************************************
4745 Check if any of the files used by src are also used by drv
4746 *********************************************************************/
4748 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
4749 struct spoolss_DriverInfo8 *src,
4750 const struct spoolss_DriverInfo8 *drv)
4752 bool in_use = False;
4758 /* check each file. Remove it from the src structure if it overlaps */
4760 if (drv_file_in_use(src->driver_path, drv)) {
4762 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
4763 src->driver_path = talloc_strdup(mem_ctx, "");
4764 if (!src->driver_path) { return false; }
4767 if (drv_file_in_use(src->data_file, drv)) {
4769 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
4770 src->data_file = talloc_strdup(mem_ctx, "");
4771 if (!src->data_file) { return false; }
4774 if (drv_file_in_use(src->config_file, drv)) {
4776 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
4777 src->config_file = talloc_strdup(mem_ctx, "");
4778 if (!src->config_file) { return false; }
4781 if (drv_file_in_use(src->help_file, drv)) {
4783 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
4784 src->help_file = talloc_strdup(mem_ctx, "");
4785 if (!src->help_file) { return false; }
4788 /* are there any dependentfiles to examine? */
4790 if (!src->dependent_files)
4793 while (src->dependent_files[i] && *src->dependent_files[i]) {
4794 if (drv_file_in_use(src->dependent_files[i], drv)) {
4796 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
4797 trim_dependent_file(mem_ctx, src->dependent_files, i);
4805 /****************************************************************************
4806 Determine whether or not a particular driver files are currently being
4807 used by any other driver.
4809 Return value is True if any files were in use by other drivers
4810 and False otherwise.
4812 Upon return, *info has been modified to only contain the driver files
4813 which are not in use
4817 This needs to check all drivers to ensure that all files in use
4818 have been removed from *info, not just the ones in the first
4820 ****************************************************************************/
4822 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
4823 struct spoolss_DriverInfo8 *info)
4828 fstring *list = NULL;
4829 struct spoolss_DriverInfo8 *driver;
4830 bool in_use = false;
4835 version = info->version;
4837 /* loop over all driver versions */
4839 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4841 /* get the list of drivers */
4844 ndrivers = get_ntdrivers(&list, info->architecture, version);
4846 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4847 ndrivers, info->architecture, version));
4849 /* check each driver for overlap in files */
4851 for (i=0; i<ndrivers; i++) {
4852 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4856 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, list[i], info->architecture, version))) {
4861 /* check if d2 uses any files from d1 */
4862 /* only if this is a different driver than the one being deleted */
4864 if (!strequal(info->driver_name, driver->driver_name)) {
4865 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
4866 /* mz: Do not instantly return -
4867 * we need to ensure this file isn't
4868 * also in use by other drivers. */
4873 free_a_printer_driver(driver);
4878 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4883 static NTSTATUS driver_unlink_internals(connection_struct *conn,
4886 struct smb_filename *smb_fname = NULL;
4889 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
4891 if (!NT_STATUS_IS_OK(status)) {
4895 status = unlink_internals(conn, NULL, 0, smb_fname, false);
4897 TALLOC_FREE(smb_fname);
4901 /****************************************************************************
4902 Actually delete the driver files. Make sure that
4903 printer_driver_files_in_use() return False before calling
4905 ****************************************************************************/
4907 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
4908 const struct spoolss_DriverInfo8 *r)
4913 connection_struct *conn;
4916 fstring printdollar;
4917 int printdollar_snum;
4924 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
4925 r->driver_name, r->version));
4927 fstrcpy(printdollar, "print$");
4929 printdollar_snum = find_service(printdollar);
4930 if (printdollar_snum == -1) {
4934 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
4935 lp_pathname(printdollar_snum),
4936 rpc_pipe->server_info, &oldcwd);
4937 if (!NT_STATUS_IS_OK(nt_status)) {
4938 DEBUG(0,("delete_driver_files: create_conn_struct "
4939 "returned %s\n", nt_errstr(nt_status)));
4943 if ( !CAN_WRITE(conn) ) {
4944 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4948 /* now delete the files; must strip the '\print$' string from
4951 if (r->driver_path && r->driver_path[0]) {
4952 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
4954 DEBUG(10,("deleting driverfile [%s]\n", s));
4955 driver_unlink_internals(conn, file);
4959 if (r->config_file && r->config_file[0]) {
4960 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
4962 DEBUG(10,("deleting configfile [%s]\n", s));
4963 driver_unlink_internals(conn, file);
4967 if (r->data_file && r->data_file[0]) {
4968 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
4970 DEBUG(10,("deleting datafile [%s]\n", s));
4971 driver_unlink_internals(conn, file);
4975 if (r->help_file && r->help_file[0]) {
4976 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
4978 DEBUG(10,("deleting helpfile [%s]\n", s));
4979 driver_unlink_internals(conn, file);
4983 /* check if we are done removing files */
4985 if (r->dependent_files) {
4986 while (r->dependent_files[i] && r->dependent_files[i][0]) {
4989 /* bypass the "\print$" portion of the path */
4991 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
4993 DEBUG(10,("deleting dependent file [%s]\n", file));
4994 driver_unlink_internals(conn, file);
5006 vfs_ChDir(conn, oldcwd);
5012 /****************************************************************************
5013 Remove a printer driver from the TDB. This assumes that the the driver was
5014 previously looked up.
5015 ***************************************************************************/
5017 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5018 const struct spoolss_DriverInfo8 *r,
5019 uint32 version, bool delete_files )
5025 /* delete the tdb data first */
5027 arch = get_short_archi(r->architecture);
5029 return WERR_UNKNOWN_PRINTER_DRIVER;
5031 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5032 arch, version, r->driver_name) < 0) {
5036 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5037 key, delete_files ? "TRUE" : "FALSE" ));
5039 /* check if the driver actually exists for this environment */
5041 dbuf = tdb_fetch_bystring( tdb_drivers, key );
5043 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5045 return WERR_UNKNOWN_PRINTER_DRIVER;
5048 SAFE_FREE( dbuf.dptr );
5050 /* ok... the driver exists so the delete should return success */
5052 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5053 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5055 return WERR_ACCESS_DENIED;
5059 * now delete any associated files if delete_files == True
5060 * even if this part failes, we return succes because the
5061 * driver doesn not exist any more
5065 delete_driver_files(rpc_pipe, r);
5067 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5073 /****************************************************************************
5074 Store a security desc for a printer.
5075 ****************************************************************************/
5077 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
5079 struct sec_desc_buf *new_secdesc_ctr = NULL;
5080 struct sec_desc_buf *old_secdesc_ctr = NULL;
5081 TALLOC_CTX *mem_ctx = NULL;
5088 mem_ctx = talloc_init("nt_printing_setsec");
5089 if (mem_ctx == NULL)
5092 /* The old owner and group sids of the security descriptor are not
5093 present when new ACEs are added or removed by changing printer
5094 permissions through NT. If they are NULL in the new security
5095 descriptor then copy them over from the old one. */
5097 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5098 struct dom_sid *owner_sid, *group_sid;
5099 struct security_acl *dacl, *sacl;
5100 struct security_descriptor *psd = NULL;
5103 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5104 status = WERR_NOMEM;
5108 /* Pick out correct owner and group sids */
5110 owner_sid = secdesc_ctr->sd->owner_sid ?
5111 secdesc_ctr->sd->owner_sid :
5112 old_secdesc_ctr->sd->owner_sid;
5114 group_sid = secdesc_ctr->sd->group_sid ?
5115 secdesc_ctr->sd->group_sid :
5116 old_secdesc_ctr->sd->group_sid;
5118 dacl = secdesc_ctr->sd->dacl ?
5119 secdesc_ctr->sd->dacl :
5120 old_secdesc_ctr->sd->dacl;
5122 sacl = secdesc_ctr->sd->sacl ?
5123 secdesc_ctr->sd->sacl :
5124 old_secdesc_ctr->sd->sacl;
5126 /* Make a deep copy of the security descriptor */
5128 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5129 owner_sid, group_sid,
5135 status = WERR_NOMEM;
5139 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5142 if (!new_secdesc_ctr) {
5143 new_secdesc_ctr = secdesc_ctr;
5146 /* Store the security descriptor in a tdb */
5148 nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5149 &blob.data, &blob.length);
5150 if (!NT_STATUS_IS_OK(nt_status)) {
5151 status = ntstatus_to_werror(nt_status);
5155 kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5157 dbuf.dptr = (unsigned char *)blob.data;
5158 dbuf.dsize = blob.length;
5160 if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5163 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5164 status = WERR_BADFUNC;
5167 /* Free malloc'ed memory */
5168 talloc_free(blob.data);
5173 talloc_destroy(mem_ctx);
5177 /****************************************************************************
5178 Construct a default security descriptor buffer for a printer.
5179 ****************************************************************************/
5181 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
5183 struct security_ace ace[7]; /* max number of ace entries */
5186 struct security_acl *psa = NULL;
5187 struct sec_desc_buf *sdb = NULL;
5188 struct security_descriptor *psd = NULL;
5189 struct dom_sid adm_sid;
5192 /* Create an ACE where Everyone is allowed to print */
5194 sa = PRINTER_ACE_PRINT;
5195 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5196 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5198 /* Add the domain admins group if we are a DC */
5201 struct dom_sid domadmins_sid;
5203 sid_compose(&domadmins_sid, get_global_sam_sid(),
5206 sa = PRINTER_ACE_FULL_CONTROL;
5207 init_sec_ace(&ace[i++], &domadmins_sid,
5208 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5209 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5210 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5211 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5213 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5214 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
5216 sa = PRINTER_ACE_FULL_CONTROL;
5217 init_sec_ace(&ace[i++], &adm_sid,
5218 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5219 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5220 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5221 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5224 /* add BUILTIN\Administrators as FULL CONTROL */
5226 sa = PRINTER_ACE_FULL_CONTROL;
5227 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5228 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5229 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5230 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5231 SEC_ACE_TYPE_ACCESS_ALLOWED,
5232 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5234 /* add BUILTIN\Print Operators as FULL CONTROL */
5236 sa = PRINTER_ACE_FULL_CONTROL;
5237 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
5238 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5239 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5240 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
5241 SEC_ACE_TYPE_ACCESS_ALLOWED,
5242 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5244 /* Make the security descriptor owned by the BUILTIN\Administrators */
5246 /* The ACL revision number in rpc_secdesc.h differs from the one
5247 created by NT when setting ACE entries in printer
5248 descriptors. NT4 complains about the property being edited by a
5251 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5252 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
5253 &global_sid_Builtin_Administrators,
5254 &global_sid_Builtin_Administrators,
5255 NULL, psa, &sd_size);
5259 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5263 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5265 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5266 (unsigned int)sd_size));
5271 /****************************************************************************
5272 Get a security desc for a printer.
5273 ****************************************************************************/
5275 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
5283 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5284 sharename = temp + 1;
5287 /* Fetch security descriptor from tdb */
5289 kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5291 dbuf = tdb_fetch(tdb_printers, kbuf);
5294 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5296 SAFE_FREE(dbuf.dptr);
5298 if (NT_STATUS_IS_OK(status)) {
5303 *secdesc_ctr = construct_default_printer_sdb(ctx);
5304 if (!*secdesc_ctr) {
5308 status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5309 &blob.data, &blob.length);
5310 if (NT_STATUS_IS_OK(status)) {
5311 dbuf.dptr = (unsigned char *)blob.data;
5312 dbuf.dsize = blob.length;
5313 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5314 talloc_free(blob.data);
5317 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5318 this security descriptor has been created when winbindd was
5319 down. Take ownership of security descriptor. */
5321 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5322 struct dom_sid owner_sid;
5324 /* Change sd owner to workgroup administrator */
5326 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5327 struct sec_desc_buf *new_secdesc_ctr = NULL;
5328 struct security_descriptor *psd = NULL;
5333 sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
5335 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5337 (*secdesc_ctr)->sd->group_sid,
5338 (*secdesc_ctr)->sd->sacl,
5339 (*secdesc_ctr)->sd->dacl,
5346 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5347 if (!new_secdesc_ctr) {
5351 /* Swap with other one */
5353 *secdesc_ctr = new_secdesc_ctr;
5357 nt_printing_setsec(sharename, *secdesc_ctr);
5361 if (DEBUGLEVEL >= 10) {
5362 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
5365 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5366 sharename, the_acl->num_aces));
5368 for (i = 0; i < the_acl->num_aces; i++) {
5369 DEBUG(10, ("%s %d %d 0x%08x\n",
5370 sid_string_dbg(&the_acl->aces[i].trustee),
5371 the_acl->aces[i].type, the_acl->aces[i].flags,
5372 the_acl->aces[i].access_mask));
5381 1: level not implemented
5382 2: file doesn't exist
5383 3: can't allocate memory
5384 4: can't free memory
5385 5: non existant struct
5389 A printer and a printer driver are 2 different things.
5390 NT manages them separatelly, Samba does the same.
5391 Why ? Simply because it's easier and it makes sense !
5393 Now explanation: You have 3 printers behind your samba server,
5394 2 of them are the same make and model (laser A and B). But laser B
5395 has an 3000 sheet feeder and laser A doesn't such an option.
5396 Your third printer is an old dot-matrix model for the accounting :-).
5398 If the /usr/local/samba/lib directory (default dir), you will have
5399 5 files to describe all of this.
5401 3 files for the printers (1 by printer):
5404 NTprinter_accounting
5405 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5406 NTdriver_printer model X
5407 NTdriver_printer model Y
5409 jfm: I should use this comment for the text file to explain
5410 same thing for the forms BTW.
5411 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5415 /* Convert generic access rights to printer object specific access rights.
5416 It turns out that NT4 security descriptors use generic access rights and
5417 NT5 the object specific ones. */
5419 void map_printer_permissions(struct security_descriptor *sd)
5423 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5424 se_map_generic(&sd->dacl->aces[i].access_mask,
5425 &printer_generic_mapping);
5429 void map_job_permissions(struct security_descriptor *sd)
5433 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5434 se_map_generic(&sd->dacl->aces[i].access_mask,
5435 &job_generic_mapping);
5440 /****************************************************************************
5441 Check a user has permissions to perform the given operation. We use the
5442 permission constants defined in include/rpc_spoolss.h to check the various
5443 actions we perform when checking printer access.
5445 PRINTER_ACCESS_ADMINISTER:
5446 print_queue_pause, print_queue_resume, update_printer_sec,
5447 update_printer, spoolss_addprinterex_level_2,
5448 _spoolss_setprinterdata
5453 JOB_ACCESS_ADMINISTER:
5454 print_job_delete, print_job_pause, print_job_resume,
5457 Try access control in the following order (for performance reasons):
5458 1) root and SE_PRINT_OPERATOR can do anything (easy check)
5459 2) check security descriptor (bit comparisons in memory)
5460 3) "printer admins" (may result in numerous calls to winbind)
5462 ****************************************************************************/
5463 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5466 struct sec_desc_buf *secdesc = NULL;
5467 uint32 access_granted;
5470 TALLOC_CTX *mem_ctx = NULL;
5471 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5473 /* If user is NULL then use the current_user structure */
5475 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5477 if (server_info->utok.uid == sec_initial_uid()
5478 || user_has_privileges(server_info->ptok, &se_printop ) ) {
5482 /* Get printer name */
5484 pname = lp_printername(snum);
5486 if (!pname || !*pname) {
5491 /* Get printer security descriptor */
5493 if(!(mem_ctx = talloc_init("print_access_check"))) {
5498 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5499 talloc_destroy(mem_ctx);
5504 if (access_type == JOB_ACCESS_ADMINISTER) {
5505 struct sec_desc_buf *parent_secdesc = secdesc;
5507 /* Create a child security descriptor to check permissions
5508 against. This is because print jobs are child objects
5509 objects of a printer. */
5511 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5513 if (!NT_STATUS_IS_OK(status)) {
5514 talloc_destroy(mem_ctx);
5515 errno = map_errno_from_nt_status(status);
5519 map_job_permissions(secdesc->sd);
5521 map_printer_permissions(secdesc->sd);
5525 status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5528 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5530 /* see if we need to try the printer admin list */
5532 if (!NT_STATUS_IS_OK(status) &&
5533 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5534 server_info->info3->base.domain.string,
5535 NULL, server_info->ptok,
5536 lp_printer_admin(snum)))) {
5537 talloc_destroy(mem_ctx);
5541 talloc_destroy(mem_ctx);
5543 if (!NT_STATUS_IS_OK(status)) {
5547 return NT_STATUS_IS_OK(status);
5550 /****************************************************************************
5551 Check the time parameters allow a print operation.
5552 *****************************************************************************/
5554 bool print_time_access_check(const char *servicename)
5556 NT_PRINTER_INFO_LEVEL *printer = NULL;
5558 time_t now = time(NULL);
5562 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5565 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5569 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5571 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5574 free_a_printer(&printer, 2);
5582 /****************************************************************************
5583 Fill in the servername sent in the _spoolss_open_printer_ex() call
5584 ****************************************************************************/
5586 char* get_server_name( Printer_entry *printer )
5588 return printer->servername;