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"
28 #include "rpc_server/srv_spoolss_util.h"
30 static TDB_CONTEXT *tdb_forms; /* used for forms files */
31 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
32 static TDB_CONTEXT *tdb_printers; /* used for printers files */
34 #define FORMS_PREFIX "FORMS/"
35 #define DRIVERS_PREFIX "DRIVERS/"
36 #define PRINTERS_PREFIX "PRINTERS/"
37 #define SECDESC_PREFIX "SECDESC/"
38 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
40 #define NTDRIVERS_DATABASE_VERSION_1 1
41 #define NTDRIVERS_DATABASE_VERSION_2 2
42 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
43 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
44 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
46 /* Map generic permissions to printer object specific permissions */
48 const struct generic_mapping printer_generic_mapping = {
55 const struct standard_mapping printer_std_mapping = {
62 /* Map generic permissions to print server object specific permissions */
64 const struct generic_mapping printserver_generic_mapping = {
71 const struct generic_mapping printserver_std_mapping = {
78 /* Map generic permissions to job object specific permissions */
80 const struct generic_mapping job_generic_mapping = {
87 /* We need one default form to support our default printer. Msoft adds the
88 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
89 array index). Letter is always first, so (for the current code) additions
90 always put things in the correct order. */
91 static const nt_forms_struct default_forms[] = {
92 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
93 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
94 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
95 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
96 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
97 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
98 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
99 {"A0",0x1,0xcd528,0x122488,0x0,0x0,0xcd528,0x122488},
100 {"A1",0x1,0x91050,0xcd528,0x0,0x0,0x91050,0xcd528},
101 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
102 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
103 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
104 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
105 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
106 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
107 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
108 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
109 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
110 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
111 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
112 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
113 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
114 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
115 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
116 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
117 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
118 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
119 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
120 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
121 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
122 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
123 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
124 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
125 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
126 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
127 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
128 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
129 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
130 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
131 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
132 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
133 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
134 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
135 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
136 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
137 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
138 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
139 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
140 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
141 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
142 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
143 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
144 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
145 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
146 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
147 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
148 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
149 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
150 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
151 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
152 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
153 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
154 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
155 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
156 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
157 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
158 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
159 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
160 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
161 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
162 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
163 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
164 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
165 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
166 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
167 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
168 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
169 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
170 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
171 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
172 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
173 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
174 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
175 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
176 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
177 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
178 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
179 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
180 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
181 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
182 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
183 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
184 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
185 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
186 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
187 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
188 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
189 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
190 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
191 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
192 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
193 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
194 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
195 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
196 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
197 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
198 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
199 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
200 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
201 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
202 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
203 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
204 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
205 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
206 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
207 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
208 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
209 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
210 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
211 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
214 static const struct print_architecture_table_node archi_table[]= {
216 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
217 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
218 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
219 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
220 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
221 {"Windows IA64", SPL_ARCH_IA64, 3 },
222 {"Windows x64", SPL_ARCH_X64, 3 },
227 /****************************************************************************
228 generate a new TDB_DATA key for storing a printer
229 ****************************************************************************/
231 static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
237 fstrcpy(share, sharename);
240 keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
241 key = string_term_tdb_data(keystr ? keystr : "");
246 /****************************************************************************
247 generate a new TDB_DATA key for storing a printer security descriptor
248 ****************************************************************************/
250 static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
251 const char* sharename )
257 fstrcpy(share, sharename );
260 keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
261 key = string_term_tdb_data(keystr ? keystr : "");
266 /****************************************************************************
267 ****************************************************************************/
269 static bool upgrade_to_version_3(void)
271 TDB_DATA kbuf, newkey, dbuf;
273 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
275 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
276 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
278 dbuf = tdb_fetch(tdb_drivers, kbuf);
280 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
281 DEBUG(0,("upgrade_to_version_3:moving form\n"));
282 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
283 SAFE_FREE(dbuf.dptr);
284 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
287 if (tdb_delete(tdb_drivers, kbuf) != 0) {
288 SAFE_FREE(dbuf.dptr);
289 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
294 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
295 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
296 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
297 SAFE_FREE(dbuf.dptr);
298 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
301 if (tdb_delete(tdb_drivers, kbuf) != 0) {
302 SAFE_FREE(dbuf.dptr);
303 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
308 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
309 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
310 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
311 SAFE_FREE(dbuf.dptr);
312 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
315 if (tdb_delete(tdb_drivers, kbuf) != 0) {
316 SAFE_FREE(dbuf.dptr);
317 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
322 SAFE_FREE(dbuf.dptr);
328 /*******************************************************************
329 Fix an issue with security descriptors. Printer sec_desc must
330 use more than the generic bits that were previously used
331 in <= 3.0.14a. They must also have a owner and group SID assigned.
332 Otherwise, any printers than have been migrated to a Windows
333 host using printmig.exe will not be accessible.
334 *******************************************************************/
336 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
337 TDB_DATA data, void *state )
340 struct sec_desc_buf *sd_orig = NULL;
341 struct sec_desc_buf *sd_new, *sd_store;
342 struct security_descriptor *sec, *new_sec;
343 TALLOC_CTX *ctx = state;
348 if (!data.dptr || data.dsize == 0) {
352 if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
356 /* upgrade the security descriptor */
358 status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
359 if (!NT_STATUS_IS_OK(status)) {
360 /* delete bad entries */
361 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
362 (const char *)key.dptr ));
363 tdb_delete( tdb_printers, key );
372 /* is this even valid? */
378 /* update access masks */
380 for ( i=0; i<sec->dacl->num_aces; i++ ) {
381 switch ( sec->dacl->aces[i].access_mask ) {
382 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
383 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
386 case GENERIC_ALL_ACCESS:
387 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
390 case READ_CONTROL_ACCESS:
391 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
393 default: /* no change */
398 /* create a new struct security_descriptor with the appropriate owner and group SIDs */
400 new_sec = make_sec_desc( ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
401 &global_sid_Builtin_Administrators,
402 &global_sid_Builtin_Administrators,
403 NULL, NULL, &size_new_sec );
407 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
412 if ( !(sd_store = sec_desc_merge_buf( ctx, sd_new, sd_orig )) ) {
413 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
419 sd_size = ndr_size_security_descriptor(sd_store->sd, 0)
420 + sizeof(struct sec_desc_buf);
422 status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
423 if (!NT_STATUS_IS_OK(status)) {
424 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
428 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
430 /* 0 to continue and non-zero to stop traversal */
432 return (result == -1);
435 /*******************************************************************
436 *******************************************************************/
438 static bool upgrade_to_version_4(void)
443 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
445 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
448 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
450 talloc_destroy( ctx );
452 return ( result != -1 );
455 /*******************************************************************
456 Fix an issue with security descriptors. Printer sec_desc must
457 use more than the generic bits that were previously used
458 in <= 3.0.14a. They must also have a owner and group SID assigned.
459 Otherwise, any printers than have been migrated to a Windows
460 host using printmig.exe will not be accessible.
461 *******************************************************************/
463 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
464 TDB_DATA data, void *state )
466 TALLOC_CTX *ctx = talloc_tos();
469 if (!data.dptr || data.dsize == 0)
472 /* upgrade printer records and security descriptors */
474 if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
475 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
477 else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
478 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
481 /* ignore this record */
485 /* delete the original record and store under the normalized key */
487 if ( tdb_delete( the_tdb, key ) != 0 ) {
488 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
493 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
494 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
502 /*******************************************************************
503 *******************************************************************/
505 static bool upgrade_to_version_5(void)
510 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
512 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
515 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
517 talloc_destroy( ctx );
519 return ( result != -1 );
522 /****************************************************************************
523 Open the NT printing tdbs. Done once before fork().
524 ****************************************************************************/
526 bool nt_printing_init(struct messaging_context *msg_ctx)
528 const char *vstring = "INFO/version";
532 if ( tdb_drivers && tdb_printers && tdb_forms )
536 tdb_close(tdb_drivers);
537 tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
539 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
540 state_path("ntdrivers.tdb"), strerror(errno) ));
545 tdb_close(tdb_printers);
546 tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
548 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
549 state_path("ntprinters.tdb"), strerror(errno) ));
554 tdb_close(tdb_forms);
555 tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
557 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
558 state_path("ntforms.tdb"), strerror(errno) ));
562 /* handle a Samba upgrade */
564 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
566 DEBUG(10, ("Fresh database\n"));
567 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
568 vers_id = NTDRIVERS_DATABASE_VERSION_5;
571 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
573 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
574 if (!upgrade_to_version_3())
576 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
577 vers_id = NTDRIVERS_DATABASE_VERSION_3;
580 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
581 /* Written on a bigendian machine with old fetch_int code. Save as le. */
582 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
583 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
584 vers_id = NTDRIVERS_DATABASE_VERSION_3;
587 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
588 if ( !upgrade_to_version_4() )
590 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
591 vers_id = NTDRIVERS_DATABASE_VERSION_4;
594 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
595 if ( !upgrade_to_version_5() )
597 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
598 vers_id = NTDRIVERS_DATABASE_VERSION_5;
602 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
603 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
608 update_c_setprinter(True);
611 * register callback to handle updating printers as new
612 * drivers are installed
615 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
616 do_drv_upgrade_printer);
618 /* of course, none of the message callbacks matter if you don't
619 tell messages.c that you interested in receiving PRINT_GENERAL
620 msgs. This is done in serverid_register() */
623 if ( lp_security() == SEC_ADS ) {
624 win_rc = check_published_printers();
625 if (!W_ERROR_IS_OK(win_rc))
626 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
632 /*******************************************************************
633 Function to allow filename parsing "the old way".
634 ********************************************************************/
636 static NTSTATUS driver_unix_convert(connection_struct *conn,
637 const char *old_name,
638 struct smb_filename **smb_fname)
641 TALLOC_CTX *ctx = talloc_tos();
642 char *name = talloc_strdup(ctx, old_name);
645 return NT_STATUS_NO_MEMORY;
648 name = unix_clean_name(ctx, name);
650 return NT_STATUS_NO_MEMORY;
652 trim_string(name,"/","/");
654 status = unix_convert(ctx, conn, name, smb_fname, 0);
655 if (!NT_STATUS_IS_OK(status)) {
656 return NT_STATUS_NO_MEMORY;
662 /*******************************************************************
663 tdb traversal function for counting printers.
664 ********************************************************************/
666 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
667 TDB_DATA data, void *context)
669 int *printer_count = (int*)context;
671 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
673 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
679 /*******************************************************************
680 Update the spooler global c_setprinter. This variable is initialized
681 when the parent smbd starts with the number of existing printers. It
682 is monotonically increased by the current number of printers *after*
683 each add or delete printer RPC. Only Microsoft knows why... JRR020119
684 ********************************************************************/
686 uint32 update_c_setprinter(bool initialize)
689 int32 printer_count = 0;
691 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
693 /* Traverse the tdb, counting the printers */
694 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
696 /* If initializing, set c_setprinter to current printers count
697 * otherwise, bump it by the current printer count
700 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
702 c_setprinter = printer_count;
704 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
705 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
707 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
709 return (uint32)c_setprinter;
712 /*******************************************************************
713 Get the spooler global c_setprinter, accounting for initialization.
714 ********************************************************************/
716 uint32 get_c_setprinter(void)
718 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
720 if (c_setprinter == (int32)-1)
721 c_setprinter = update_c_setprinter(True);
723 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
725 return (uint32)c_setprinter;
728 /****************************************************************************
729 Get builtin form struct list.
730 ****************************************************************************/
732 int get_builtin_ntforms(nt_forms_struct **list)
734 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
738 return ARRAY_SIZE(default_forms);
741 /****************************************************************************
742 get a builtin form struct
743 ****************************************************************************/
745 bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
748 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
749 for (i=0; i<ARRAY_SIZE(default_forms); i++) {
750 if (strequal(form_name,default_forms[i].name)) {
751 DEBUGADD(6,("Found builtin form %s \n", form_name));
752 memcpy(form,&default_forms[i],sizeof(*form));
760 /****************************************************************************
761 get a form struct list.
762 ****************************************************************************/
764 int get_ntforms(nt_forms_struct **list)
766 TDB_DATA kbuf, newkey, dbuf;
767 nt_forms_struct form;
774 for (kbuf = tdb_firstkey(tdb_forms);
776 newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
778 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
781 dbuf = tdb_fetch(tdb_forms, kbuf);
785 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
786 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
787 &i, &form.flag, &form.width, &form.length, &form.left,
788 &form.top, &form.right, &form.bottom);
789 SAFE_FREE(dbuf.dptr);
790 if (ret != dbuf.dsize)
793 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
795 DEBUG(0,("get_ntforms: Realloc fail.\n"));
806 /****************************************************************************
807 write a form struct list
808 ****************************************************************************/
810 int write_ntforms(nt_forms_struct **list, int number)
812 TALLOC_CTX *ctx = talloc_tos();
819 for (i=0;i<number;i++) {
820 /* save index, so list is rebuilt in correct order */
821 len = tdb_pack(NULL, 0, "dddddddd",
822 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
823 (*list)[i].left, (*list)[i].top, (*list)[i].right,
828 buf = TALLOC_ARRAY(ctx, char, len);
832 len = tdb_pack((uint8 *)buf, len, "dddddddd",
833 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
834 (*list)[i].left, (*list)[i].top, (*list)[i].right,
836 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
841 dbuf.dptr = (uint8 *)buf;
842 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
854 /****************************************************************************
855 add a form struct at the end of the list
856 ****************************************************************************/
857 bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count)
863 * NT tries to add forms even when
864 * they are already in the base
865 * only update the values if already present
870 for (n=0; n<*count; n++) {
871 if ( strequal((*list)[n].name, form->form_name) ) {
878 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
879 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
882 fstrcpy((*list)[n].name, form->form_name);
886 (*list)[n].flag = form->flags;
887 (*list)[n].width = form->size.width;
888 (*list)[n].length = form->size.height;
889 (*list)[n].left = form->area.left;
890 (*list)[n].top = form->area.top;
891 (*list)[n].right = form->area.right;
892 (*list)[n].bottom = form->area.bottom;
894 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
895 update ? "updated" : "added", form->form_name));
900 /****************************************************************************
901 Delete a named form struct.
902 ****************************************************************************/
904 bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
911 for (n=0; n<*count; n++) {
912 if (!strncmp((*list)[n].name, del_name, strlen(del_name))) {
913 DEBUG(103, ("delete_a_form, [%s] in list\n", del_name));
919 DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
920 *ret = WERR_INVALID_FORM_NAME;
924 if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
928 if (tdb_delete_bystring(tdb_forms, key) != 0) {
937 /****************************************************************************
938 Update a form struct.
939 ****************************************************************************/
941 void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
945 DEBUG(106, ("[%s]\n", form->form_name));
946 for (n=0; n<count; n++) {
947 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
948 if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name)))
952 if (n==count) return;
954 (*list)[n].flag = form->flags;
955 (*list)[n].width = form->size.width;
956 (*list)[n].length = form->size.height;
957 (*list)[n].left = form->area.left;
958 (*list)[n].top = form->area.top;
959 (*list)[n].right = form->area.right;
960 (*list)[n].bottom = form->area.bottom;
963 /****************************************************************************
964 Get the nt drivers list.
965 Traverse the database and look-up the matching names.
966 ****************************************************************************/
967 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
970 const char *short_archi;
972 TDB_DATA kbuf, newkey;
974 short_archi = get_short_archi(architecture);
979 if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
980 short_archi, version) < 0) {
984 for (kbuf = tdb_firstkey(tdb_drivers);
986 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
988 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
991 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
992 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
997 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
1005 /****************************************************************************
1006 Function to do the mapping between the long architecture name and
1008 ****************************************************************************/
1010 const char *get_short_archi(const char *long_archi)
1014 DEBUG(107,("Getting architecture dependant directory\n"));
1017 } while ( (archi_table[i].long_archi!=NULL ) &&
1018 StrCaseCmp(long_archi, archi_table[i].long_archi) );
1020 if (archi_table[i].long_archi==NULL) {
1021 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1025 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1027 DEBUGADD(108,("index: [%d]\n", i));
1028 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1029 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1031 return archi_table[i].short_archi;
1034 /****************************************************************************
1035 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1036 There are two case to be covered here: PE (Portable Executable) and NE (New
1037 Executable) files. Both files support the same INFO structure, but PE files
1038 store the signature in unicode, and NE files store it as !unicode.
1039 returns -1 on error, 1 on version info found, and 0 on no version info found.
1040 ****************************************************************************/
1042 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1048 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1049 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1050 fname, DOS_HEADER_SIZE));
1054 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1055 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1056 fname, (unsigned long)byte_count));
1057 goto no_version_info;
1060 /* Is this really a DOS header? */
1061 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1062 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1063 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1064 goto no_version_info;
1067 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1068 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1069 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1071 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1072 goto no_version_info;
1075 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1076 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1077 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1078 fname, (unsigned long)byte_count));
1079 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1080 goto no_version_info;
1083 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1084 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1085 unsigned int num_sections;
1086 unsigned int section_table_bytes;
1088 /* Just skip over optional header to get to section table */
1089 if (SMB_VFS_LSEEK(fsp,
1090 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1091 SEEK_CUR) == (SMB_OFF_T)-1) {
1092 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1097 /* get the section table */
1098 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1099 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1100 if (section_table_bytes == 0)
1104 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1105 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1106 fname, section_table_bytes));
1110 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1111 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1112 fname, (unsigned long)byte_count));
1116 /* Iterate the section table looking for the resource section ".rsrc" */
1117 for (i = 0; i < num_sections; i++) {
1118 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1120 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1121 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1122 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1124 if (section_bytes == 0)
1128 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1129 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1130 fname, section_bytes));
1134 /* Seek to the start of the .rsrc section info */
1135 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1136 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1141 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1142 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1143 fname, (unsigned long)byte_count));
1147 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1150 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1151 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1152 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1153 /* Align to next long address */
1154 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1156 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1157 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1158 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1160 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1161 fname, *major, *minor,
1162 (*major>>16)&0xffff, *major&0xffff,
1163 (*minor>>16)&0xffff, *minor&0xffff));
1172 /* Version info not found, fall back to origin date/time */
1173 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1177 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1178 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1179 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1180 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1181 /* At this point, we assume the file is in error. It still could be somthing
1182 * else besides a NE file, but it unlikely at this point. */
1186 /* Allocate a bit more space to speed up things */
1188 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1189 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1190 fname, PE_HEADER_SIZE));
1194 /* This is a HACK! I got tired of trying to sort through the messy
1195 * 'NE' file format. If anyone wants to clean this up please have at
1196 * it, but this works. 'NE' files will eventually fade away. JRR */
1197 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1198 /* Cover case that should not occur in a well formed 'NE' .dll file */
1199 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1201 for(i=0; i<byte_count; i++) {
1202 /* Fast skip past data that can't possibly match */
1203 if (buf[i] != 'V') continue;
1205 /* Potential match data crosses buf boundry, move it to beginning
1206 * of buf, and fill the buf with as much as it will hold. */
1207 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1210 memcpy(buf, &buf[i], byte_count-i);
1211 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1212 (byte_count-i))) < 0) {
1214 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1219 byte_count = bc + (byte_count - i);
1220 if (byte_count<VS_VERSION_INFO_SIZE) break;
1225 /* Check that the full signature string and the magic number that
1226 * follows exist (not a perfect solution, but the chances that this
1227 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1228 * twice, as it is simpler to read the code. */
1229 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1230 /* Compute skip alignment to next long address */
1231 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1232 sizeof(VS_SIGNATURE)) & 3;
1233 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1235 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1236 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1237 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1238 fname, *major, *minor,
1239 (*major>>16)&0xffff, *major&0xffff,
1240 (*minor>>16)&0xffff, *minor&0xffff));
1247 /* Version info not found, fall back to origin date/time */
1248 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1253 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1254 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1255 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1266 /****************************************************************************
1267 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1268 share one or more files. During the MS installation process files are checked
1269 to insure that only a newer version of a shared file is installed over an
1270 older version. There are several possibilities for this comparison. If there
1271 is no previous version, the new one is newer (obviously). If either file is
1272 missing the version info structure, compare the creation date (on Unix use
1273 the modification date). Otherwise chose the numerically larger version number.
1274 ****************************************************************************/
1276 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1278 bool use_version = true;
1282 time_t new_create_time;
1286 time_t old_create_time;
1288 struct smb_filename *smb_fname = NULL;
1289 files_struct *fsp = NULL;
1295 SET_STAT_INVALID(st);
1296 new_create_time = (time_t)0;
1297 old_create_time = (time_t)0;
1299 /* Get file version info (if available) for previous file (if it exists) */
1300 status = driver_unix_convert(conn, old_file, &smb_fname);
1301 if (!NT_STATUS_IS_OK(status)) {
1305 status = SMB_VFS_CREATE_FILE(
1308 0, /* root_dir_fid */
1309 smb_fname, /* fname */
1310 FILE_GENERIC_READ, /* access_mask */
1311 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1312 FILE_OPEN, /* create_disposition*/
1313 0, /* create_options */
1314 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1315 INTERNAL_OPEN_ONLY, /* oplock_request */
1316 0, /* allocation_size */
1317 0, /* private_flags */
1323 if (!NT_STATUS_IS_OK(status)) {
1324 /* Old file not found, so by definition new file is in fact newer */
1325 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
1326 "errno = %d\n", smb_fname_str_dbg(smb_fname),
1332 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1338 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1340 use_version = false;
1341 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1344 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1345 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1346 (long)old_create_time));
1349 close_file(NULL, fsp, NORMAL_CLOSE);
1352 /* Get file version info (if available) for new file */
1353 status = driver_unix_convert(conn, new_file, &smb_fname);
1354 if (!NT_STATUS_IS_OK(status)) {
1358 status = SMB_VFS_CREATE_FILE(
1361 0, /* root_dir_fid */
1362 smb_fname, /* fname */
1363 FILE_GENERIC_READ, /* access_mask */
1364 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1365 FILE_OPEN, /* create_disposition*/
1366 0, /* create_options */
1367 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1368 INTERNAL_OPEN_ONLY, /* oplock_request */
1369 0, /* allocation_size */
1370 0, /* private_flags */
1376 if (!NT_STATUS_IS_OK(status)) {
1377 /* New file not found, this shouldn't occur if the caller did its job */
1378 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
1379 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
1383 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1389 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1391 use_version = false;
1392 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1395 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1396 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1397 (long)new_create_time));
1400 close_file(NULL, fsp, NORMAL_CLOSE);
1403 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1404 /* Compare versions and choose the larger version number */
1405 if (new_major > old_major ||
1406 (new_major == old_major && new_minor > old_minor)) {
1408 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1413 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1419 /* Compare modification time/dates and choose the newest time/date */
1420 if (new_create_time > old_create_time) {
1421 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1426 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1434 close_file(NULL, fsp, NORMAL_CLOSE);
1437 TALLOC_FREE(smb_fname);
1441 /****************************************************************************
1442 Determine the correct cVersion associated with an architecture and driver
1443 ****************************************************************************/
1444 static uint32 get_correct_cversion(struct pipes_struct *p,
1445 const char *architecture,
1446 const char *driverpath_in,
1451 struct smb_filename *smb_fname = NULL;
1452 char *driverpath = NULL;
1453 files_struct *fsp = NULL;
1454 connection_struct *conn = NULL;
1457 fstring printdollar;
1458 int printdollar_snum;
1460 *perr = WERR_INVALID_PARAM;
1462 /* If architecture is Windows 95/98/ME, the version is always 0. */
1463 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1464 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1469 /* If architecture is Windows x64, the version is always 3. */
1470 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1471 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1476 fstrcpy(printdollar, "print$");
1478 printdollar_snum = find_service(printdollar);
1479 if (printdollar_snum == -1) {
1480 *perr = WERR_NO_SUCH_SHARE;
1484 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1485 lp_pathname(printdollar_snum),
1486 p->server_info, &oldcwd);
1487 if (!NT_STATUS_IS_OK(nt_status)) {
1488 DEBUG(0,("get_correct_cversion: create_conn_struct "
1489 "returned %s\n", nt_errstr(nt_status)));
1490 *perr = ntstatus_to_werror(nt_status);
1494 /* Open the driver file (Portable Executable format) and determine the
1495 * deriver the cversion. */
1496 driverpath = talloc_asprintf(talloc_tos(),
1505 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
1506 if (!NT_STATUS_IS_OK(nt_status)) {
1507 *perr = ntstatus_to_werror(nt_status);
1511 nt_status = vfs_file_exist(conn, smb_fname);
1512 if (!NT_STATUS_IS_OK(nt_status)) {
1513 *perr = WERR_BADFILE;
1517 status = SMB_VFS_CREATE_FILE(
1520 0, /* root_dir_fid */
1521 smb_fname, /* fname */
1522 FILE_GENERIC_READ, /* access_mask */
1523 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1524 FILE_OPEN, /* create_disposition*/
1525 0, /* create_options */
1526 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1527 INTERNAL_OPEN_ONLY, /* oplock_request */
1528 0, /* private_flags */
1529 0, /* allocation_size */
1535 if (!NT_STATUS_IS_OK(status)) {
1536 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1537 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1538 *perr = WERR_ACCESS_DENIED;
1545 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1546 if (ret == -1) goto error_exit;
1549 DEBUG(6,("get_correct_cversion: Version info not "
1551 smb_fname_str_dbg(smb_fname)));
1556 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1557 * for more details. Version in this case is not just the version of the
1558 * file, but the version in the sense of kernal mode (2) vs. user mode
1559 * (3) drivers. Other bits of the version fields are the version info.
1562 cversion = major & 0x0000ffff;
1564 case 2: /* WinNT drivers */
1565 case 3: /* Win2K drivers */
1569 DEBUG(6,("get_correct_cversion: cversion "
1570 "invalid [%s] cversion = %d\n",
1571 smb_fname_str_dbg(smb_fname),
1576 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1577 " = 0x%x minor = 0x%x\n",
1578 smb_fname_str_dbg(smb_fname), major, minor));
1581 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1582 smb_fname_str_dbg(smb_fname), cversion));
1589 TALLOC_FREE(smb_fname);
1591 close_file(NULL, fsp, NORMAL_CLOSE);
1594 vfs_ChDir(conn, oldcwd);
1597 if (cversion != -1) {
1603 /****************************************************************************
1604 ****************************************************************************/
1606 #define strip_driver_path(_mem_ctx, _element) do { \
1607 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1608 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1609 W_ERROR_HAVE_NO_MEMORY((_element)); \
1613 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1614 struct pipes_struct *rpc_pipe,
1615 const char *architecture,
1616 const char **driver_path,
1617 const char **data_file,
1618 const char **config_file,
1619 const char **help_file,
1620 struct spoolss_StringArray *dependent_files,
1623 const char *short_architecture;
1628 if (!*driver_path || !*data_file || !*config_file) {
1629 return WERR_INVALID_PARAM;
1632 /* clean up the driver name.
1633 * we can get .\driver.dll
1634 * or worse c:\windows\system\driver.dll !
1636 /* using an intermediate string to not have overlaping memcpy()'s */
1638 strip_driver_path(mem_ctx, *driver_path);
1639 strip_driver_path(mem_ctx, *data_file);
1640 strip_driver_path(mem_ctx, *config_file);
1642 strip_driver_path(mem_ctx, *help_file);
1645 if (dependent_files && dependent_files->string) {
1646 for (i=0; dependent_files->string[i]; i++) {
1647 strip_driver_path(mem_ctx, dependent_files->string[i]);
1651 short_architecture = get_short_archi(architecture);
1652 if (!short_architecture) {
1653 return WERR_UNKNOWN_PRINTER_DRIVER;
1656 /* jfm:7/16/2000 the client always sends the cversion=0.
1657 * The server should check which version the driver is by reading
1658 * the PE header of driver->driverpath.
1660 * For Windows 95/98 the version is 0 (so the value sent is correct)
1661 * For Windows NT (the architecture doesn't matter)
1662 * NT 3.1: cversion=0
1663 * NT 3.5/3.51: cversion=1
1668 *version = get_correct_cversion(rpc_pipe, short_architecture,
1669 *driver_path, &err);
1670 if (*version == -1) {
1677 /****************************************************************************
1678 ****************************************************************************/
1680 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1681 struct pipes_struct *rpc_pipe,
1682 struct spoolss_AddDriverInfoCtr *r)
1686 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
1687 r->info.info3->architecture,
1688 &r->info.info3->driver_path,
1689 &r->info.info3->data_file,
1690 &r->info.info3->config_file,
1691 &r->info.info3->help_file,
1692 r->info.info3->dependent_files,
1693 &r->info.info3->version);
1695 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
1696 r->info.info6->architecture,
1697 &r->info.info6->driver_path,
1698 &r->info.info6->data_file,
1699 &r->info.info6->config_file,
1700 &r->info.info6->help_file,
1701 r->info.info6->dependent_files,
1702 &r->info.info6->version);
1704 return WERR_NOT_SUPPORTED;
1708 /****************************************************************************
1709 This function sucks and should be replaced. JRA.
1710 ****************************************************************************/
1712 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1713 const struct spoolss_AddDriverInfo6 *src)
1715 dst->version = src->version;
1717 dst->driver_name = src->driver_name;
1718 dst->architecture = src->architecture;
1719 dst->driver_path = src->driver_path;
1720 dst->data_file = src->data_file;
1721 dst->config_file = src->config_file;
1722 dst->help_file = src->help_file;
1723 dst->monitor_name = src->monitor_name;
1724 dst->default_datatype = src->default_datatype;
1725 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1726 dst->dependent_files = src->dependent_files;
1729 /****************************************************************************
1730 This function sucks and should be replaced. JRA.
1731 ****************************************************************************/
1733 static void convert_level_8_to_level3(TALLOC_CTX *mem_ctx,
1734 struct spoolss_AddDriverInfo3 *dst,
1735 const struct spoolss_DriverInfo8 *src)
1737 dst->version = src->version;
1738 dst->driver_name = src->driver_name;
1739 dst->architecture = src->architecture;
1740 dst->driver_path = src->driver_path;
1741 dst->data_file = src->data_file;
1742 dst->config_file = src->config_file;
1743 dst->help_file = src->help_file;
1744 dst->monitor_name = src->monitor_name;
1745 dst->default_datatype = src->default_datatype;
1746 if (src->dependent_files) {
1747 dst->dependent_files = talloc_zero(mem_ctx, struct spoolss_StringArray);
1748 if (!dst->dependent_files) return;
1749 dst->dependent_files->string = src->dependent_files;
1751 dst->dependent_files = NULL;
1755 /****************************************************************************
1756 ****************************************************************************/
1758 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1759 connection_struct *conn,
1760 const char *driver_file,
1761 const char *short_architecture,
1762 uint32_t driver_version,
1765 struct smb_filename *smb_fname_old = NULL;
1766 struct smb_filename *smb_fname_new = NULL;
1767 char *old_name = NULL;
1768 char *new_name = NULL;
1772 old_name = talloc_asprintf(mem_ctx, "%s/%s",
1773 short_architecture, driver_file);
1774 W_ERROR_HAVE_NO_MEMORY(old_name);
1776 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1777 short_architecture, driver_version, driver_file);
1778 if (new_name == NULL) {
1779 TALLOC_FREE(old_name);
1783 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1785 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1786 if (!NT_STATUS_IS_OK(status)) {
1791 /* Setup a synthetic smb_filename struct */
1792 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
1793 if (!smb_fname_new) {
1798 smb_fname_new->base_name = new_name;
1800 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1801 "'%s'\n", smb_fname_old->base_name,
1802 smb_fname_new->base_name));
1804 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1805 OPENX_FILE_EXISTS_TRUNCATE |
1806 OPENX_FILE_CREATE_IF_NOT_EXIST,
1809 if (!NT_STATUS_IS_OK(status)) {
1810 DEBUG(0,("move_driver_file_to_download_area: Unable "
1811 "to rename [%s] to [%s]: %s\n",
1812 smb_fname_old->base_name, new_name,
1813 nt_errstr(status)));
1814 ret = WERR_ACCESS_DENIED;
1821 TALLOC_FREE(smb_fname_old);
1822 TALLOC_FREE(smb_fname_new);
1826 WERROR move_driver_to_download_area(struct pipes_struct *p,
1827 struct spoolss_AddDriverInfoCtr *r,
1830 struct spoolss_AddDriverInfo3 *driver;
1831 struct spoolss_AddDriverInfo3 converted_driver;
1832 const char *short_architecture;
1833 struct smb_filename *smb_dname = NULL;
1834 char *new_dir = NULL;
1835 connection_struct *conn = NULL;
1838 TALLOC_CTX *ctx = talloc_tos();
1841 fstring printdollar;
1842 int printdollar_snum;
1848 driver = r->info.info3;
1851 convert_level_6_to_level3(&converted_driver, r->info.info6);
1852 driver = &converted_driver;
1855 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1856 return WERR_UNKNOWN_LEVEL;
1859 short_architecture = get_short_archi(driver->architecture);
1860 if (!short_architecture) {
1861 return WERR_UNKNOWN_PRINTER_DRIVER;
1864 fstrcpy(printdollar, "print$");
1866 printdollar_snum = find_service(printdollar);
1867 if (printdollar_snum == -1) {
1868 *perr = WERR_NO_SUCH_SHARE;
1869 return WERR_NO_SUCH_SHARE;
1872 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1873 lp_pathname(printdollar_snum),
1874 p->server_info, &oldcwd);
1875 if (!NT_STATUS_IS_OK(nt_status)) {
1876 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1877 "returned %s\n", nt_errstr(nt_status)));
1878 *perr = ntstatus_to_werror(nt_status);
1882 new_dir = talloc_asprintf(ctx,
1890 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1891 if (!NT_STATUS_IS_OK(nt_status)) {
1896 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1898 create_directory(conn, NULL, smb_dname);
1900 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1901 * listed for this driver which has already been moved, skip it (note:
1902 * drivers may list the same file name several times. Then check if the
1903 * file already exists in archi\version\, if so, check that the version
1904 * info (or time stamps if version info is unavailable) is newer (or the
1905 * date is later). If it is, move it to archi\version\filexxx.yyy.
1906 * Otherwise, delete the file.
1908 * If a file is not moved to archi\version\ because of an error, all the
1909 * rest of the 'unmoved' driver files are removed from archi\. If one or
1910 * more of the driver's files was already moved to archi\version\, it
1911 * potentially leaves the driver in a partially updated state. Version
1912 * trauma will most likely occur if an client attempts to use any printer
1913 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1914 * done is appropriate... later JRR
1917 DEBUG(5,("Moving files now !\n"));
1919 if (driver->driver_path && strlen(driver->driver_path)) {
1921 *perr = move_driver_file_to_download_area(ctx,
1923 driver->driver_path,
1927 if (!W_ERROR_IS_OK(*perr)) {
1928 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1935 if (driver->data_file && strlen(driver->data_file)) {
1936 if (!strequal(driver->data_file, driver->driver_path)) {
1938 *perr = move_driver_file_to_download_area(ctx,
1944 if (!W_ERROR_IS_OK(*perr)) {
1945 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1953 if (driver->config_file && strlen(driver->config_file)) {
1954 if (!strequal(driver->config_file, driver->driver_path) &&
1955 !strequal(driver->config_file, driver->data_file)) {
1957 *perr = move_driver_file_to_download_area(ctx,
1959 driver->config_file,
1963 if (!W_ERROR_IS_OK(*perr)) {
1964 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1972 if (driver->help_file && strlen(driver->help_file)) {
1973 if (!strequal(driver->help_file, driver->driver_path) &&
1974 !strequal(driver->help_file, driver->data_file) &&
1975 !strequal(driver->help_file, driver->config_file)) {
1977 *perr = move_driver_file_to_download_area(ctx,
1983 if (!W_ERROR_IS_OK(*perr)) {
1984 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1992 if (driver->dependent_files && driver->dependent_files->string) {
1993 for (i=0; driver->dependent_files->string[i]; i++) {
1994 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1995 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1996 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1997 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1999 for (j=0; j < i; j++) {
2000 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
2005 *perr = move_driver_file_to_download_area(ctx,
2007 driver->dependent_files->string[i],
2011 if (!W_ERROR_IS_OK(*perr)) {
2012 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
2023 TALLOC_FREE(smb_dname);
2026 vfs_ChDir(conn, oldcwd);
2030 if (W_ERROR_EQUAL(*perr, WERR_OK)) {
2034 return WERR_UNKNOWN_PRINTER_DRIVER;
2039 /****************************************************************************
2040 ****************************************************************************/
2042 static uint32 add_a_printer_driver_3(struct spoolss_AddDriverInfo3 *driver)
2044 TALLOC_CTX *ctx = talloc_tos();
2046 const char *architecture;
2047 char *directory = NULL;
2053 architecture = get_short_archi(driver->architecture);
2054 if (!architecture) {
2058 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2059 * \\server is added in the rpc server layer.
2060 * It does make sense to NOT store the server's name in the printer TDB.
2063 directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
2064 architecture, driver->version);
2069 #define gen_full_driver_unc_path(ctx, directory, file) \
2071 if (file && strlen(file)) { \
2072 file = talloc_asprintf(ctx, "%s%s", directory, file); \
2074 file = talloc_strdup(ctx, ""); \
2077 return (uint32_t)-1; \
2081 /* .inf files do not always list a file for each of the four standard files.
2082 * Don't prepend a path to a null filename, or client claims:
2083 * "The server on which the printer resides does not have a suitable
2084 * <printer driver name> printer driver installed. Click OK if you
2085 * wish to install the driver on your local machine."
2088 gen_full_driver_unc_path(ctx, directory, driver->driver_path);
2089 gen_full_driver_unc_path(ctx, directory, driver->data_file);
2090 gen_full_driver_unc_path(ctx, directory, driver->config_file);
2091 gen_full_driver_unc_path(ctx, directory, driver->help_file);
2093 if (driver->dependent_files && driver->dependent_files->string) {
2094 for (i=0; driver->dependent_files->string[i]; i++) {
2095 gen_full_driver_unc_path(ctx, directory,
2096 driver->dependent_files->string[i]);
2100 key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
2101 architecture, driver->version, driver->driver_name);
2106 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
2113 len += tdb_pack(buf+len, buflen-len, "dffffffff",
2115 driver->driver_name,
2116 driver->architecture,
2117 driver->driver_path,
2119 driver->config_file,
2121 driver->monitor_name ? driver->monitor_name : "",
2122 driver->default_datatype ? driver->default_datatype : "");
2124 if (driver->dependent_files && driver->dependent_files->string) {
2125 for (i=0; driver->dependent_files->string[i]; i++) {
2126 len += tdb_pack(buf+len, buflen-len, "f",
2127 driver->dependent_files->string[i]);
2131 if (len != buflen) {
2132 buf = (uint8 *)SMB_REALLOC(buf, len);
2134 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2145 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2149 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2155 /****************************************************************************
2156 ****************************************************************************/
2158 static uint32_t add_a_printer_driver_8(struct spoolss_DriverInfo8 *driver)
2160 TALLOC_CTX *mem_ctx = talloc_new(talloc_tos());
2161 struct spoolss_AddDriverInfo3 info3;
2164 convert_level_8_to_level3(mem_ctx, &info3, driver);
2166 ret = add_a_printer_driver_3(&info3);
2167 talloc_free(mem_ctx);
2172 /****************************************************************************
2173 ****************************************************************************/
2175 static WERROR get_a_printer_driver_3_default(TALLOC_CTX *mem_ctx,
2176 struct spoolss_DriverInfo3 *info,
2177 const char *driver, const char *arch)
2179 info->driver_name = talloc_strdup(mem_ctx, driver);
2180 if (!info->driver_name) {
2184 info->default_datatype = talloc_strdup(mem_ctx, "RAW");
2185 if (!info->default_datatype) {
2189 info->driver_path = talloc_strdup(mem_ctx, "");
2190 info->data_file = talloc_strdup(mem_ctx, "");
2191 info->config_file = talloc_strdup(mem_ctx, "");
2192 info->help_file = talloc_strdup(mem_ctx, "");
2193 if (!info->driver_path || !info->data_file || !info->config_file || !info->help_file) {
2200 /****************************************************************************
2201 ****************************************************************************/
2203 static WERROR get_a_printer_driver_3(TALLOC_CTX *mem_ctx,
2204 struct spoolss_DriverInfo3 *driver,
2205 const char *drivername, const char *arch,
2209 const char *architecture;
2213 fstring name, driverpath, environment, datafile, configfile, helpfile, monitorname, defaultdatatype;
2215 architecture = get_short_archi(arch);
2216 if ( !architecture ) {
2217 return WERR_UNKNOWN_PRINTER_DRIVER;
2220 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2222 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2225 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2227 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
2228 architecture, version, drivername) < 0) {
2232 dbuf = tdb_fetch_bystring(tdb_drivers, key);
2235 return WERR_UNKNOWN_PRINTER_DRIVER;
2238 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2249 driver->driver_name = talloc_strdup(mem_ctx, name);
2250 driver->architecture = talloc_strdup(mem_ctx, environment);
2251 driver->driver_path = talloc_strdup(mem_ctx, driverpath);
2252 driver->data_file = talloc_strdup(mem_ctx, datafile);
2253 driver->config_file = talloc_strdup(mem_ctx, configfile);
2254 driver->help_file = talloc_strdup(mem_ctx, helpfile);
2255 driver->monitor_name = talloc_strdup(mem_ctx, monitorname);
2256 driver->default_datatype = talloc_strdup(mem_ctx, defaultdatatype);
2260 while (len < dbuf.dsize) {
2264 driver->dependent_files = talloc_realloc(mem_ctx, driver->dependent_files, const char *, i+2);
2265 if (!driver->dependent_files ) {
2266 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2270 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2273 driver->dependent_files[i] = talloc_strdup(mem_ctx, file);
2278 if (driver->dependent_files)
2279 driver->dependent_files[i] = NULL;
2281 SAFE_FREE(dbuf.dptr);
2284 if (len != dbuf.dsize) {
2285 return get_a_printer_driver_3_default(mem_ctx, driver, drivername, arch);
2291 /****************************************************************************
2292 ****************************************************************************/
2293 int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8 *buf, int buflen)
2295 enum ndr_err_code ndr_err;
2300 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
2302 (ndr_push_flags_fn_t)
2303 ndr_push_spoolss_DeviceMode);
2304 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2305 DEBUG(10, ("pack_devicemode: "
2306 "error encoding spoolss_DeviceMode\n"));
2313 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
2316 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
2323 /****************************************************************************
2324 ****************************************************************************/
2325 int unpack_devicemode(TALLOC_CTX *mem_ctx,
2326 const uint8 *buf, int buflen,
2327 struct spoolss_DeviceMode **devmode)
2329 struct spoolss_DeviceMode *dm;
2330 enum ndr_err_code ndr_err;
2338 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
2343 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2348 blob = data_blob_const(data, data_len);
2350 ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
2351 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
2352 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2353 DEBUG(10, ("unpack_devicemode: "
2354 "error parsing spoolss_DeviceMode\n"));
2358 DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
2359 dm->devicename, dm->formname));
2360 if (dm->driverextra_data.data) {
2361 DEBUG(8, ("with a private section of %d bytes\n",
2362 dm->__driverextra_length));
2372 /****************************************************************************
2373 Pack all values in all printer keys
2374 ***************************************************************************/
2376 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2380 struct regval_blob *val;
2381 struct regval_ctr *val_ctr;
2388 /* loop over all keys */
2390 for ( i=0; i<data->num_keys; i++ ) {
2391 val_ctr = data->keys[i].values;
2392 num_values = regval_ctr_numvals( val_ctr );
2394 /* pack the keyname followed by a empty value */
2396 len += tdb_pack(buf+len, buflen-len, "pPdB",
2397 &data->keys[i].name,
2403 /* now loop over all values */
2405 for ( j=0; j<num_values; j++ ) {
2406 /* pathname should be stored as <key>\<value> */
2408 val = regval_ctr_specific_value( val_ctr, j );
2409 if (asprintf(&path, "%s\\%s",
2411 regval_name(val)) < 0) {
2415 len += tdb_pack(buf+len, buflen-len, "pPdB",
2420 regval_data_p(val) );
2422 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2430 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2436 /****************************************************************************
2437 Delete a printer - this just deletes the printer info file, any open
2438 handles are not affected.
2439 ****************************************************************************/
2441 uint32 del_a_printer(const char *sharename)
2444 char *printdb_path = NULL;
2445 TALLOC_CTX *ctx = talloc_tos();
2447 kbuf = make_printer_tdbkey(ctx, sharename);
2448 tdb_delete(tdb_printers, kbuf);
2450 kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2451 tdb_delete(tdb_printers, kbuf);
2453 close_all_print_db();
2455 if (geteuid() == sec_initial_uid()) {
2456 if (asprintf(&printdb_path, "%s%s.tdb",
2457 cache_path("printing/"),
2461 unlink(printdb_path);
2462 SAFE_FREE(printdb_path);
2468 /****************************************************************************
2469 ****************************************************************************/
2470 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2476 TDB_DATA kbuf, dbuf;
2479 * in addprinter: no servername and the printer is the name
2480 * in setprinter: servername is \\server
2481 * and printer is \\server\\printer
2483 * Samba manages only local printers.
2484 * we currently don't support things like i
2485 * path=\\other_server\printer
2487 * We only store the printername, not \\server\printername
2490 if ( info->servername[0] != '\0' ) {
2491 trim_string(info->printername, info->servername, NULL);
2492 trim_char(info->printername, '\\', '\0');
2493 info->servername[0]='\0';
2497 * JFM: one day I'll forget.
2498 * below that's info->portname because that's the SAMBA sharename
2499 * and I made NT 'thinks' it's the portname
2500 * the info->sharename is the thing you can name when you add a printer
2501 * that's the short-name when you create shared printer for 95/98
2502 * So I've made a limitation in SAMBA: you can only have 1 printer model
2503 * behind a SAMBA share.
2511 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2514 info->default_priority,
2531 info->printprocessor,
2535 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2536 retlen = pack_values( info->data, buf+len, buflen-len );
2543 if (buflen != len) {
2544 buf = (uint8 *)SMB_REALLOC(buf, len);
2546 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2554 kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2559 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2562 if (!W_ERROR_IS_OK(ret))
2563 DEBUG(8, ("error updating printer to tdb on disk\n"));
2567 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2568 info->sharename, info->drivername, info->portname, len));
2573 /****************************************************************************
2574 Create and allocate a default devicemode.
2575 ****************************************************************************/
2577 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
2578 const char *devicename,
2579 struct spoolss_DeviceMode **devmode)
2581 struct spoolss_DeviceMode *dm;
2584 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2589 dname = talloc_asprintf(dm, "%s", devicename);
2590 if (dname == NULL) {
2593 if (strlen(dname) > MAXDEVICENAME) {
2594 dname[MAXDEVICENAME] = '\0';
2596 dm->devicename = dname;
2598 dm->formname = talloc_strdup(dm, "Letter");
2599 if (dm->formname == NULL) {
2603 dm->specversion = DMSPEC_NT4_AND_ABOVE;
2604 dm->driverversion = 0x0400;
2606 dm->__driverextra_length = 0;
2607 dm->fields = DEVMODE_FORMNAME |
2609 DEVMODE_PRINTQUALITY |
2610 DEVMODE_DEFAULTSOURCE |
2614 DEVMODE_ORIENTATION;
2615 dm->orientation = DMORIENT_PORTRAIT;
2616 dm->papersize = DMPAPER_LETTER;
2617 dm->paperlength = 0;
2621 dm->defaultsource = DMBIN_FORMSOURCE;
2622 dm->printquality = DMRES_HIGH; /* 0x0258 */
2623 dm->color = DMRES_MONOCHROME;
2624 dm->duplex = DMDUP_SIMPLEX;
2625 dm->yresolution = 0;
2626 dm->ttoption = DMTT_SUBDEV;
2627 dm->collate = DMCOLLATE_FALSE;
2637 dm->displayflags = 0;
2638 dm->displayfrequency = 0;
2641 dm->panningwidth = 0;
2642 dm->panningheight = 0;
2644 dm->driverextra_data.data = NULL;
2645 dm->driverextra_data.length = 0;
2651 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
2652 struct spoolss_security_descriptor **secdesc)
2654 struct security_ace ace[7]; /* max number of ace entries */
2657 struct security_acl *psa = NULL;
2658 struct security_descriptor *psd = NULL;
2659 struct dom_sid adm_sid;
2662 /* Create an ACE where Everyone is allowed to print */
2664 sa = PRINTER_ACE_PRINT;
2665 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2666 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2668 /* Add the domain admins group if we are a DC */
2671 struct dom_sid domadmins_sid;
2673 sid_compose(&domadmins_sid, get_global_sam_sid(),
2676 sa = PRINTER_ACE_FULL_CONTROL;
2677 init_sec_ace(&ace[i++], &domadmins_sid,
2678 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2679 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2680 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2681 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2683 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
2684 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
2686 sa = PRINTER_ACE_FULL_CONTROL;
2687 init_sec_ace(&ace[i++], &adm_sid,
2688 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2689 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2690 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2691 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2694 /* add BUILTIN\Administrators as FULL CONTROL */
2696 sa = PRINTER_ACE_FULL_CONTROL;
2697 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2698 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2699 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2700 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2701 SEC_ACE_TYPE_ACCESS_ALLOWED,
2702 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2704 /* add BUILTIN\Print Operators as FULL CONTROL */
2706 sa = PRINTER_ACE_FULL_CONTROL;
2707 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2708 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2709 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2710 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2711 SEC_ACE_TYPE_ACCESS_ALLOWED,
2712 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2714 /* Make the security descriptor owned by the BUILTIN\Administrators */
2716 /* The ACL revision number in rpc_secdesc.h differs from the one
2717 created by NT when setting ACE entries in printer
2718 descriptors. NT4 complains about the property being edited by a
2721 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
2722 psd = make_sec_desc(mem_ctx,
2724 SEC_DESC_SELF_RELATIVE,
2725 &global_sid_Builtin_Administrators,
2726 &global_sid_Builtin_Administrators,
2733 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2737 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2738 (unsigned int)sd_size));
2745 /****************************************************************************
2746 Allocate and initialize a new slot.
2747 ***************************************************************************/
2749 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2755 if ( !name || !data )
2758 /* allocate another slot in the NT_PRINTER_KEY array */
2760 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2761 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2767 key_index = data->num_keys;
2769 /* initialze new key */
2771 data->keys[key_index].name = talloc_strdup( data, name );
2773 werr = regval_ctr_init(data, &(data->keys[key_index].values));
2774 if (!W_ERROR_IS_OK(werr)) {
2780 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2785 /****************************************************************************
2786 search for a registry key name in the existing printer data
2787 ***************************************************************************/
2789 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2793 for ( i=0; i<data->num_keys; i++ ) {
2794 if ( strequal( data->keys[i].name, name ) ) {
2796 /* cleanup memory */
2798 TALLOC_FREE( data->keys[i].name );
2799 TALLOC_FREE( data->keys[i].values );
2801 /* if not the end of the array, move remaining elements down one slot */
2804 if ( data->num_keys && (i < data->num_keys) )
2805 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2812 return data->num_keys;
2815 /****************************************************************************
2816 search for a registry key name in the existing printer data
2817 ***************************************************************************/
2819 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2824 if ( !data || !name )
2827 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2829 /* loop over all existing keys */
2831 for ( i=0; i<data->num_keys; i++ ) {
2832 if ( strequal(data->keys[i].name, name) ) {
2833 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2843 /****************************************************************************
2844 ***************************************************************************/
2846 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2850 int num_subkeys = 0;
2852 fstring *subkeys_ptr = NULL;
2863 /* special case of asking for the top level printer data registry key names */
2865 if ( strlen(key) == 0 ) {
2866 for ( i=0; i<data->num_keys; i++ ) {
2868 /* found a match, so allocate space and copy the name */
2870 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2871 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2876 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2883 /* asking for the subkeys of some key */
2884 /* subkey paths are stored in the key name using '\' as the delimiter */
2886 for ( i=0; i<data->num_keys; i++ ) {
2887 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2889 /* if we found the exact key, then break */
2890 key_len = strlen( key );
2891 if ( strlen(data->keys[i].name) == key_len )
2894 /* get subkey path */
2896 p = data->keys[i].name + key_len;
2899 fstrcpy( subkeyname, p );
2900 if ( (p = strchr( subkeyname, '\\' )) )
2903 /* don't add a key more than once */
2905 for ( j=0; j<num_subkeys; j++ ) {
2906 if ( strequal( subkeys_ptr[j], subkeyname ) )
2910 if ( j != num_subkeys )
2913 /* found a match, so allocate space and copy the name */
2915 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2916 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2921 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2927 /* return error if the key was not found */
2929 if ( i == data->num_keys ) {
2930 SAFE_FREE(subkeys_ptr);
2935 /* tag off the end */
2938 fstrcpy(subkeys_ptr[num_subkeys], "" );
2940 *subkeys = subkeys_ptr;
2946 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
2949 regval_ctr_delvalue(ctr, val_name);
2950 regval_ctr_addvalue_sz(ctr, val_name, sz);
2953 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
2956 regval_ctr_delvalue(ctr, val_name);
2957 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2958 (uint8 *) &dword, sizeof(dword));
2961 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
2964 uint8 bin_bool = (b ? 1 : 0);
2965 regval_ctr_delvalue(ctr, val_name);
2966 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2967 (uint8 *) &bin_bool, sizeof(bin_bool));
2970 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
2971 const char *multi_sz)
2978 regval_ctr_delvalue(ctr, val_name);
2979 regval_ctr_addvalue_multi_sz(ctr, val_name, a);
2982 /****************************************************************************
2983 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2985 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2986 * @return bool indicating success or failure
2987 ***************************************************************************/
2989 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2991 struct regval_ctr *ctr = NULL;
2993 const char *dnssuffix;
2994 char *allocated_string = NULL;
2995 const char *ascii_str;
2998 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2999 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3000 ctr = info2->data->keys[i].values;
3002 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3003 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3005 /* we make the assumption that the netbios name is the same
3006 as the DNS name sinc ethe former will be what we used to
3009 dnssuffix = get_mydnsdomname(talloc_tos());
3010 if (dnssuffix && *dnssuffix) {
3011 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3013 fstrcpy( longname, global_myname() );
3016 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3018 if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3021 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3022 SAFE_FREE(allocated_string);
3024 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3025 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3026 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3027 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3028 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3029 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3030 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3031 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3032 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3034 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3035 (info2->attributes &
3036 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3038 switch (info2->attributes & 0x3) {
3040 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3043 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3046 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3049 ascii_str = "unknown";
3051 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3056 /*****************************************************************
3057 ****************************************************************/
3059 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3063 struct regval_ctr *ctr=NULL;
3065 /* find the DsSpooler key */
3066 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3067 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3068 ctr = info2->data->keys[i].values;
3070 regval_ctr_delvalue(ctr, "objectGUID");
3072 /* We used to store this as a REG_BINARY but that causes
3075 regval_ctr_addvalue_sz(ctr, "objectGUID",
3076 GUID_string(talloc_tos(), &guid));
3079 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3080 NT_PRINTER_INFO_LEVEL *printer)
3084 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3085 char *srv_dn_utf8, **srv_cn_utf8;
3088 const char *attrs[] = {"objectGUID", NULL};
3090 WERROR win_rc = WERR_OK;
3091 size_t converted_size;
3093 /* build the ads mods */
3094 ctx = talloc_init("nt_printer_publish_ads");
3099 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3101 /* figure out where to publish */
3102 ads_find_machine_acct(ads, &res, global_myname());
3104 /* We use ldap_get_dn here as we need the answer
3105 * in utf8 to call ldap_explode_dn(). JRA. */
3107 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3110 return WERR_SERVER_UNAVAILABLE;
3112 ads_msgfree(ads, res);
3113 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3116 ldap_memfree(srv_dn_utf8);
3117 return WERR_SERVER_UNAVAILABLE;
3119 /* Now convert to CH_UNIX. */
3120 if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3122 ldap_memfree(srv_dn_utf8);
3123 ldap_memfree(srv_cn_utf8);
3124 return WERR_SERVER_UNAVAILABLE;
3126 if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3128 ldap_memfree(srv_dn_utf8);
3129 ldap_memfree(srv_cn_utf8);
3130 TALLOC_FREE(srv_dn);
3131 return WERR_SERVER_UNAVAILABLE;
3134 ldap_memfree(srv_dn_utf8);
3135 ldap_memfree(srv_cn_utf8);
3137 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3138 if (!srv_cn_escaped) {
3140 return WERR_SERVER_UNAVAILABLE;
3142 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3143 if (!sharename_escaped) {
3144 SAFE_FREE(srv_cn_escaped);
3146 return WERR_SERVER_UNAVAILABLE;
3149 prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3151 SAFE_FREE(srv_cn_escaped);
3152 SAFE_FREE(sharename_escaped);
3154 mods = ads_init_mods(ctx);
3162 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3163 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3164 printer->info_2->sharename);
3167 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3168 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3170 for (i=0; mods[i] != 0; i++)
3172 mods[i] = (LDAPMod *)-1;
3173 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3176 if (!ADS_ERR_OK(ads_rc))
3177 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3179 /* retreive the guid and store it locally */
3180 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3182 ads_pull_guid(ads, res, &guid);
3183 ads_msgfree(ads, res);
3184 store_printer_guid(printer->info_2, guid);
3185 win_rc = mod_a_printer(printer, 2);
3192 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3193 NT_PRINTER_INFO_LEVEL *printer)
3196 LDAPMessage *res = NULL;
3197 char *prt_dn = NULL;
3199 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3201 /* remove the printer from the directory */
3202 ads_rc = ads_find_printer_on_server(ads, &res,
3203 printer->info_2->sharename, global_myname());
3205 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3206 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3208 ads_msgfree(ads, res);
3211 ads_rc = ads_del_dn(ads, prt_dn);
3212 TALLOC_FREE(prt_dn);
3216 ads_msgfree(ads, res);
3221 /****************************************************************************
3222 * Publish a printer in the directory
3224 * @param snum describing printer service
3225 * @return WERROR indicating status of publishing
3226 ***************************************************************************/
3228 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3231 ADS_STRUCT *ads = NULL;
3232 NT_PRINTER_INFO_LEVEL *printer = NULL;
3235 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3236 if (!W_ERROR_IS_OK(win_rc))
3240 case DSPRINT_PUBLISH:
3241 case DSPRINT_UPDATE:
3242 /* set the DsSpooler info and attributes */
3243 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3244 win_rc = WERR_NOMEM;
3248 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3250 case DSPRINT_UNPUBLISH:
3251 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3254 win_rc = WERR_NOT_SUPPORTED;
3258 win_rc = mod_a_printer(printer, 2);
3259 if (!W_ERROR_IS_OK(win_rc)) {
3260 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3264 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3266 DEBUG(3, ("ads_init() failed\n"));
3267 win_rc = WERR_SERVER_UNAVAILABLE;
3270 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3271 SAFE_FREE(ads->auth.password);
3272 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3275 /* ads_connect() will find the DC for us */
3276 ads_rc = ads_connect(ads);
3277 if (!ADS_ERR_OK(ads_rc)) {
3278 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3279 win_rc = WERR_ACCESS_DENIED;
3284 case DSPRINT_PUBLISH:
3285 case DSPRINT_UPDATE:
3286 win_rc = nt_printer_publish_ads(ads, printer);
3288 case DSPRINT_UNPUBLISH:
3289 win_rc = nt_printer_unpublish_ads(ads, printer);
3294 free_a_printer(&printer, 2);
3299 WERROR check_published_printers(void)
3302 ADS_STRUCT *ads = NULL;
3304 int n_services = lp_numservices();
3305 NT_PRINTER_INFO_LEVEL *printer = NULL;
3307 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3309 DEBUG(3, ("ads_init() failed\n"));
3310 return WERR_SERVER_UNAVAILABLE;
3312 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3313 SAFE_FREE(ads->auth.password);
3314 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3317 /* ads_connect() will find the DC for us */
3318 ads_rc = ads_connect(ads);
3319 if (!ADS_ERR_OK(ads_rc)) {
3320 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3322 ads_kdestroy("MEMORY:prtpub_cache");
3323 return WERR_ACCESS_DENIED;
3326 for (snum = 0; snum < n_services; snum++) {
3327 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3330 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3331 lp_servicename(snum))) &&
3332 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3333 nt_printer_publish_ads(ads, printer);
3335 free_a_printer(&printer, 2);
3339 ads_kdestroy("MEMORY:prtpub_cache");
3343 bool is_printer_published(Printer_entry *print_hnd, int snum,
3346 NT_PRINTER_INFO_LEVEL *printer = NULL;
3347 struct regval_ctr *ctr;
3348 struct regval_blob *guid_val;
3354 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3356 if (!W_ERROR_IS_OK(win_rc) ||
3357 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3358 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3359 !(ctr = printer->info_2->data->keys[i].values) ||
3360 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3362 free_a_printer(&printer, 2);
3366 /* fetching printer guids really ought to be a separate function. */
3371 /* We used to store the guid as REG_BINARY, then swapped
3372 to REG_SZ for Vista compatibility so check for both */
3374 switch ( regval_type(guid_val) ){
3376 blob = data_blob_const(regval_data_p(guid_val),
3377 regval_size(guid_val));
3378 pull_reg_sz(talloc_tos(), &blob, (const char **)&guid_str);
3379 ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3380 talloc_free(guid_str);
3383 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3387 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3390 DEBUG(0,("is_printer_published: GUID value stored as "
3391 "invaluid type (%d)\n", regval_type(guid_val) ));
3396 free_a_printer(&printer, 2);
3400 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3405 WERROR check_published_printers(void)
3410 bool is_printer_published(Printer_entry *print_hnd, int snum,
3415 #endif /* HAVE_ADS */
3417 /****************************************************************************
3418 ***************************************************************************/
3420 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3422 NT_PRINTER_DATA *data;
3424 int removed_keys = 0;
3428 empty_slot = data->num_keys;
3431 return WERR_INVALID_PARAM;
3433 /* remove all keys */
3435 if ( !strlen(key) ) {
3437 TALLOC_FREE( data );
3441 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3447 /* remove a specific key (and all subkeys) */
3449 for ( i=0; i<data->num_keys; i++ ) {
3450 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3451 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3452 data->keys[i].name));
3454 TALLOC_FREE( data->keys[i].name );
3455 TALLOC_FREE( data->keys[i].values );
3457 /* mark the slot as empty */
3459 ZERO_STRUCTP( &data->keys[i] );
3463 /* find the first empty slot */
3465 for ( i=0; i<data->num_keys; i++ ) {
3466 if ( !data->keys[i].name ) {
3473 if ( i == data->num_keys )
3474 /* nothing was removed */
3475 return WERR_INVALID_PARAM;
3477 /* move everything down */
3479 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3480 if ( data->keys[i].name ) {
3481 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3482 ZERO_STRUCTP( &data->keys[i] );
3490 data->num_keys -= removed_keys;
3492 /* sanity check to see if anything is left */
3494 if ( !data->num_keys ) {
3495 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3497 SAFE_FREE( data->keys );
3498 ZERO_STRUCTP( data );
3504 /****************************************************************************
3505 ***************************************************************************/
3507 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3509 WERROR result = WERR_OK;
3512 /* we must have names on non-zero length */
3514 if ( !key || !*key|| !value || !*value )
3515 return WERR_INVALID_NAME;
3517 /* find the printer key first */
3519 key_index = lookup_printerkey( p2->data, key );
3520 if ( key_index == -1 )
3523 /* make sure the value exists so we can return the correct error code */
3525 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3526 return WERR_BADFILE;
3528 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3530 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3536 /****************************************************************************
3537 ***************************************************************************/
3539 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3540 uint32 type, uint8 *data, int real_len )
3542 WERROR result = WERR_OK;
3545 /* we must have names on non-zero length */
3547 if ( !key || !*key|| !value || !*value )
3548 return WERR_INVALID_NAME;
3550 /* find the printer key first */
3552 key_index = lookup_printerkey( p2->data, key );
3553 if ( key_index == -1 )
3554 key_index = add_new_printer_key( p2->data, key );
3556 if ( key_index == -1 )
3559 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3560 type, data, real_len );
3562 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3563 key, value, type, real_len ));
3568 /****************************************************************************
3569 ***************************************************************************/
3571 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3575 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3578 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3581 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3584 /****************************************************************************
3585 Unpack a list of registry values frem the TDB
3586 ***************************************************************************/
3588 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3593 const char *valuename = NULL;
3594 const char *keyname = NULL;
3598 struct regval_blob *regval_p;
3601 /* add the "PrinterDriverData" key first for performance reasons */
3603 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3605 /* loop and unpack the rest of the registry values */
3609 /* check to see if there are any more registry values */
3612 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3616 /* unpack the next regval */
3618 len += tdb_unpack(buf+len, buflen-len, "fdB",
3624 /* lookup for subkey names which have a type of REG_NONE */
3625 /* there's no data with this entry */
3627 if ( type == REG_NONE ) {
3628 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3629 add_new_printer_key( printer_data, string );
3634 * break of the keyname from the value name.
3635 * Valuenames can have embedded '\'s so be careful.
3636 * only support one level of keys. See the
3637 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3641 str = strchr_m( string, '\\');
3643 /* Put in "PrinterDriverData" is no key specified */
3646 keyname = SPOOL_PRINTERDATA_KEY;
3655 /* see if we need a new key */
3657 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3658 key_index = add_new_printer_key( printer_data, keyname );
3660 if ( key_index == -1 ) {
3661 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3666 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3668 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3669 Thanks to Martin Zielinski for the hint. */
3671 if ( type == REG_BINARY &&
3672 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3673 strequal( valuename, "objectGUID" ) )
3677 /* convert the GUID to a UNICODE string */
3679 memcpy( &guid, data_p, sizeof(struct GUID) );
3681 regval_ctr_addvalue_sz(printer_data->keys[key_index].values,
3683 GUID_string(talloc_tos(), &guid));
3688 regval_ctr_addvalue( printer_data->keys[key_index].values,
3689 valuename, type, data_p,
3693 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3700 /****************************************************************************
3701 ***************************************************************************/
3703 static char *win_driver;
3704 static char *os2_driver;
3706 static const char *get_win_driver(void)
3708 if (win_driver == NULL) {
3714 static const char *get_os2_driver(void)
3716 if (os2_driver == NULL) {
3722 static bool set_driver_mapping(const char *from, const char *to)
3724 SAFE_FREE(win_driver);
3725 SAFE_FREE(os2_driver);
3727 win_driver = SMB_STRDUP(from);
3728 os2_driver = SMB_STRDUP(to);
3730 if (win_driver == NULL || os2_driver == NULL) {
3731 SAFE_FREE(win_driver);
3732 SAFE_FREE(os2_driver);
3738 static void map_to_os2_driver(fstring drivername)
3740 char *mapfile = lp_os2_driver_map();
3741 char **lines = NULL;
3745 if (!strlen(drivername))
3751 if (strequal(drivername, get_win_driver())) {
3752 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3753 drivername, get_os2_driver()));
3754 fstrcpy(drivername, get_os2_driver());
3758 lines = file_lines_load(mapfile, &numlines,0,NULL);
3759 if (numlines == 0 || lines == NULL) {
3760 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3765 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3767 for( i = 0; i < numlines; i++) {
3768 char *nt_name = lines[i];
3769 char *os2_name = strchr(nt_name,'=');
3776 while (isspace(*nt_name))
3779 if (!*nt_name || strchr("#;",*nt_name))
3783 int l = strlen(nt_name);
3784 while (l && isspace(nt_name[l-1])) {
3790 while (isspace(*os2_name))
3794 int l = strlen(os2_name);
3795 while (l && isspace(os2_name[l-1])) {
3801 if (strequal(nt_name,drivername)) {
3802 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3803 set_driver_mapping(drivername,os2_name);
3804 fstrcpy(drivername,os2_name);
3816 * @brief Map a Windows driver to a OS/2 driver.
3818 * @param[in] mem_ctx The memory context to use.
3820 * @param[in,out] pdrivername The drivername of Windows to remap.
3822 * @return WERR_OK on success, a corresponding WERROR on failure.
3824 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
3826 const char *mapfile = lp_os2_driver_map();
3827 char **lines = NULL;
3828 const char *drivername;
3832 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
3833 return WERR_INVALID_PARAMETER;
3836 drivername = *pdrivername;
3838 if (mapfile[0] == '\0') {
3839 return WERR_BADFILE;
3842 if (strequal(drivername, get_win_driver())) {
3843 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3844 drivername, get_os2_driver()));
3845 drivername = talloc_strdup(mem_ctx, get_os2_driver());
3846 if (drivername == NULL) {
3849 *pdrivername = drivername;
3853 lines = file_lines_load(mapfile, &numlines, 0, NULL);
3854 if (numlines == 0 || lines == NULL) {
3855 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
3860 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3862 for( i = 0; i < numlines; i++) {
3863 char *nt_name = lines[i];
3864 char *os2_name = strchr(nt_name, '=');
3866 if (os2_name == NULL) {
3872 while (isspace(*nt_name)) {
3876 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
3881 int l = strlen(nt_name);
3882 while (l && isspace(nt_name[l - 1])) {
3888 while (isspace(*os2_name)) {
3893 int l = strlen(os2_name);
3894 while (l && isspace(os2_name[l-1])) {
3900 if (strequal(nt_name, drivername)) {
3901 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
3902 set_driver_mapping(drivername, os2_name);
3903 drivername = talloc_strdup(mem_ctx, os2_name);
3905 if (drivername == NULL) {
3908 *pdrivername = drivername;
3917 /****************************************************************************
3918 Get a default printer info 2 struct.
3919 ****************************************************************************/
3921 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
3922 const char *servername,
3923 const char* sharename,
3926 int snum = lp_servicenumber(sharename);
3929 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3930 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3931 servername, sharename);
3932 fstrcpy(info->sharename, sharename);
3933 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3935 /* by setting the driver name to an empty string, a local NT admin
3936 can now run the **local** APW to install a local printer driver
3937 for a Samba shared printer in 2.2. Without this, drivers **must** be
3938 installed on the Samba server for NT clients --jerry */
3939 #if 0 /* JERRY --do not uncomment-- */
3940 if (!*info->drivername)
3941 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3945 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3947 strlcpy(info->comment, "", sizeof(info->comment));
3948 fstrcpy(info->printprocessor, "winprint");
3949 fstrcpy(info->datatype, "RAW");
3952 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3953 /* Pull the location and comment strings from cups if we don't
3955 if ( !strlen(info->location) || !strlen(info->comment) ) {
3956 char *comment = NULL;
3957 char *location = NULL;
3958 if (cups_pull_comment_location(info, info->sharename,
3959 &comment, &location)) {
3960 strlcpy(info->comment, comment, sizeof(info->comment));
3961 fstrcpy(info->location, location);
3962 TALLOC_FREE(comment);
3963 TALLOC_FREE(location);
3969 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3971 info->starttime = 0; /* Minutes since 12:00am GMT */
3972 info->untiltime = 0; /* Minutes since 12:00am GMT */
3974 info->default_priority = 1;
3975 info->setuptime = (uint32)time(NULL);
3978 * I changed this as I think it is better to have a generic
3979 * DEVMODE than to crash Win2k explorer.exe --jerry
3980 * See the HP Deskjet 990c Win2k drivers for an example.
3982 * However the default devmode appears to cause problems
3983 * with the HP CLJ 8500 PCL driver. Hence the addition of
3984 * the "default devmode" parameter --jerry 22/01/2002
3987 if (lp_default_devmode(snum)) {
3988 result = spoolss_create_default_devmode(info,
3991 if (!W_ERROR_IS_OK(result)) {
3995 info->devmode = NULL;
3998 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4002 info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
4007 add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
4012 TALLOC_FREE(info->devmode);
4014 return WERR_ACCESS_DENIED;
4017 /****************************************************************************
4018 ****************************************************************************/
4020 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
4021 const char *servername,
4022 const char *sharename,
4026 int snum = lp_servicenumber(sharename);
4027 TDB_DATA kbuf, dbuf;
4028 fstring printername;
4029 char *comment = NULL;
4032 kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4034 dbuf = tdb_fetch(tdb_printers, kbuf);
4036 return get_a_printer_2_default(info, servername,
4037 sharename, get_loc_com);
4040 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4043 &info->default_priority,
4050 &info->c_setprinter,
4060 info->printprocessor,
4065 strlcpy(info->comment, comment, sizeof(info->comment));
4069 /* Samba has to have shared raw drivers. */
4070 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4071 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4073 /* Restore the stripped strings. */
4074 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4076 if ( lp_force_printername(snum) ) {
4077 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4079 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4082 fstrcpy(info->printername, printername);
4085 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4086 /* Pull the location and comment strings from cups if we don't
4088 if ( !strlen(info->location) || !strlen(info->comment) ) {
4089 char *location = NULL;
4091 if (cups_pull_comment_location(info, info->sharename,
4092 &comment, &location)) {
4093 strlcpy(info->comment, comment, sizeof(info->comment));
4094 fstrcpy(info->location, location);
4095 TALLOC_FREE(comment);
4096 TALLOC_FREE(location);
4102 len += unpack_devicemode(info, dbuf.dptr+len,
4107 * Some client drivers freak out if there is a NULL devmode
4108 * (probably the driver is not checking before accessing
4109 * the devmode pointer) --jerry
4111 * See comments in get_a_printer_2_default()
4114 if (lp_default_devmode(snum) && !info->devmode) {
4115 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4117 result = spoolss_create_default_devmode(info, printername,
4119 if (!W_ERROR_IS_OK(result)) {
4124 if (info->devmode) {
4125 info->devmode->devicename = talloc_strdup(info->devmode,
4127 if (!info->devmode->devicename) {
4128 result = WERR_NOMEM;
4133 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4134 DEBUG(0,("unpack_values: talloc() failed!\n"));
4135 result = WERR_NOMEM;
4138 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4140 /* This will get the current RPC talloc context, but we should be
4141 passing this as a parameter... fixme... JRA ! */
4143 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4144 result = WERR_NOMEM;
4148 /* Fix for OS/2 drivers. */
4150 if (get_remote_arch() == RA_OS2) {
4151 map_to_os2_driver(info->drivername);
4154 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4155 sharename, info->printername, info->drivername));
4160 SAFE_FREE(dbuf.dptr);
4164 /****************************************************************************
4165 Debugging function, dump at level 6 the struct in the logs.
4166 ****************************************************************************/
4167 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4170 NT_PRINTER_INFO_LEVEL_2 *info2;
4172 DEBUG(106,("Dumping printer at level [%d]\n", level));
4177 if (printer->info_2 == NULL)
4181 info2=printer->info_2;
4183 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4184 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4185 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4186 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4187 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4188 DEBUGADD(106,("status:[%d]\n", info2->status));
4189 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4190 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4191 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4192 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4193 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4195 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4196 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4197 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4198 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4199 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4200 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4201 DEBUGADD(106,("location:[%s]\n", info2->location));
4202 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4203 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4204 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4205 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4211 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4219 /****************************************************************************
4220 Update the changeid time.
4221 This is SO NASTY as some drivers need this to change, others need it
4222 static. This value will change every second, and I must hope that this
4223 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4225 ****************************************************************************/
4227 static uint32 rev_changeid(void)
4231 get_process_uptime(&tv);
4234 /* Return changeid as msec since spooler restart */
4235 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4238 * This setting seems to work well but is too untested
4239 * to replace the above calculation. Left in for experiementation
4240 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4242 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4248 * The function below are the high level ones.
4249 * only those ones must be called from the spoolss code.
4253 /****************************************************************************
4254 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4255 ****************************************************************************/
4257 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4261 dump_a_printer(printer, level);
4267 * Update the changestamp. Emperical tests show that the
4268 * ChangeID is always updated,but c_setprinter is
4269 * global spooler variable (not per printer).
4272 /* ChangeID **must** be increasing over the lifetime
4273 of client's spoolss service in order for the
4274 client's cache to show updates */
4276 printer->info_2->changeid = rev_changeid();
4279 * Because one day someone will ask:
4280 * NT->NT An admin connection to a remote
4281 * printer show changes imeediately in
4282 * the properities dialog
4284 * A non-admin connection will only show the
4285 * changes after viewing the properites page
4286 * 2 times. Seems to be related to a
4287 * race condition in the client between the spooler
4288 * updating the local cache and the Explorer.exe GUI
4289 * actually displaying the properties.
4291 * This is fixed in Win2k. admin/non-admin
4292 * connections both display changes immediately.
4297 result=update_a_printer_2(printer->info_2);
4301 result=WERR_UNKNOWN_LEVEL;
4308 /****************************************************************************
4309 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4311 Previously the code had a memory allocation problem because it always
4312 used the TALLOC_CTX from the Printer_entry*. This context lasts
4313 as a long as the original handle is open. So if the client made a lot
4314 of getprinter[data]() calls, the memory usage would climb. Now we use
4315 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4316 still use the Printer_entry->ctx for maintaining the cache copy though
4317 since that object must live as long as the handle by definition.
4320 ****************************************************************************/
4322 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4323 const char *sharename, bool get_loc_com)
4328 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4330 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4331 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4337 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4338 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4339 TALLOC_FREE( *pp_printer );
4344 fstrcpy( servername, print_hnd->servername );
4346 fstrcpy( servername, "%L" );
4347 standard_sub_basic( "", "", servername,
4348 sizeof(servername)-1 );
4351 result = get_a_printer_2( (*pp_printer)->info_2,
4352 servername, sharename, get_loc_com);
4354 /* we have a new printer now. Save it with this handle */
4356 if ( !W_ERROR_IS_OK(result) ) {
4357 TALLOC_FREE( *pp_printer );
4358 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4359 sharename, (unsigned int)level, win_errstr(result)));
4363 dump_a_printer( *pp_printer, level);
4368 TALLOC_FREE( *pp_printer );
4369 return WERR_UNKNOWN_LEVEL;
4375 WERROR get_a_printer( Printer_entry *print_hnd,
4376 NT_PRINTER_INFO_LEVEL **pp_printer,
4378 const char *sharename)
4380 return get_a_printer_internal(print_hnd, pp_printer, level,
4384 WERROR get_a_printer_search( Printer_entry *print_hnd,
4385 NT_PRINTER_INFO_LEVEL **pp_printer,
4387 const char *sharename)
4389 return get_a_printer_internal(print_hnd, pp_printer, level,
4393 /****************************************************************************
4394 Deletes a NT_PRINTER_INFO_LEVEL struct.
4395 ****************************************************************************/
4397 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4399 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4406 TALLOC_FREE(printer->info_2);
4410 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4414 TALLOC_FREE(*pp_printer);
4419 /****************************************************************************
4420 ****************************************************************************/
4422 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
4423 struct spoolss_DriverInfo8 *_info8)
4425 struct spoolss_DriverInfo8 info8;
4431 info8.version = r->info.info3->version;
4432 info8.driver_name = r->info.info3->driver_name;
4433 info8.architecture = r->info.info3->architecture;
4434 info8.driver_path = r->info.info3->driver_path;
4435 info8.data_file = r->info.info3->data_file;
4436 info8.config_file = r->info.info3->config_file;
4437 info8.help_file = r->info.info3->help_file;
4438 info8.monitor_name = r->info.info3->monitor_name;
4439 info8.default_datatype = r->info.info3->default_datatype;
4440 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
4441 info8.dependent_files = r->info.info3->dependent_files->string;
4445 info8.version = r->info.info6->version;
4446 info8.driver_name = r->info.info6->driver_name;
4447 info8.architecture = r->info.info6->architecture;
4448 info8.driver_path = r->info.info6->driver_path;
4449 info8.data_file = r->info.info6->data_file;
4450 info8.config_file = r->info.info6->config_file;
4451 info8.help_file = r->info.info6->help_file;
4452 info8.monitor_name = r->info.info6->monitor_name;
4453 info8.default_datatype = r->info.info6->default_datatype;
4454 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
4455 info8.dependent_files = r->info.info6->dependent_files->string;
4457 info8.driver_date = r->info.info6->driver_date;
4458 info8.driver_version = r->info.info6->driver_version;
4459 info8.manufacturer_name = r->info.info6->manufacturer_name;
4460 info8.manufacturer_url = r->info.info6->manufacturer_url;
4461 info8.hardware_id = r->info.info6->hardware_id;
4462 info8.provider = r->info.info6->provider;
4465 info8.version = r->info.info8->version;
4466 info8.driver_name = r->info.info8->driver_name;
4467 info8.architecture = r->info.info8->architecture;
4468 info8.driver_path = r->info.info8->driver_path;
4469 info8.data_file = r->info.info8->data_file;
4470 info8.config_file = r->info.info8->config_file;
4471 info8.help_file = r->info.info8->help_file;
4472 info8.monitor_name = r->info.info8->monitor_name;
4473 info8.default_datatype = r->info.info8->default_datatype;
4474 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
4475 info8.dependent_files = r->info.info8->dependent_files->string;
4477 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
4478 info8.previous_names = r->info.info8->previous_names->string;
4480 info8.driver_date = r->info.info8->driver_date;
4481 info8.driver_version = r->info.info8->driver_version;
4482 info8.manufacturer_name = r->info.info8->manufacturer_name;
4483 info8.manufacturer_url = r->info.info8->manufacturer_url;
4484 info8.hardware_id = r->info.info8->hardware_id;
4485 info8.provider = r->info.info8->provider;
4486 info8.print_processor = r->info.info8->print_processor;
4487 info8.vendor_setup = r->info.info8->vendor_setup;
4488 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
4489 info8.color_profiles = r->info.info8->color_profiles->string;
4491 info8.inf_path = r->info.info8->inf_path;
4492 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
4493 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
4494 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
4496 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
4497 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
4509 uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx,
4510 struct spoolss_AddDriverInfoCtr *r,
4514 struct spoolss_DriverInfo8 info8;
4518 DEBUG(10,("adding a printer at level [%d]\n", r->level));
4520 if (!driver_info_ctr_to_info8(r, &info8)) {
4524 *driver_name = talloc_strdup(mem_ctx, info8.driver_name);
4525 if (!*driver_name) {
4528 *version = info8.version;
4530 return add_a_printer_driver_8(&info8);
4533 /****************************************************************************
4534 ****************************************************************************/
4536 WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx,
4537 struct spoolss_DriverInfo8 **driver,
4538 const char *drivername, const char *architecture,
4542 struct spoolss_DriverInfo3 info3;
4543 struct spoolss_DriverInfo8 *info8;
4547 /* Sometime we just want any version of the driver */
4549 if (version == DRIVER_ANY_VERSION) {
4550 /* look for Win2k first and then for NT4 */
4551 result = get_a_printer_driver_3(mem_ctx,
4555 if (!W_ERROR_IS_OK(result)) {
4556 result = get_a_printer_driver_3(mem_ctx,
4562 result = get_a_printer_driver_3(mem_ctx,
4569 if (!W_ERROR_IS_OK(result)) {
4573 info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8);
4578 info8->version = info3.version;
4579 info8->driver_name = info3.driver_name;
4580 info8->architecture = info3.architecture;
4581 info8->driver_path = info3.driver_path;
4582 info8->data_file = info3.data_file;
4583 info8->config_file = info3.config_file;
4584 info8->help_file = info3.help_file;
4585 info8->dependent_files = info3.dependent_files;
4586 info8->monitor_name = info3.monitor_name;
4587 info8->default_datatype = info3.default_datatype;
4594 /****************************************************************************
4595 ****************************************************************************/
4597 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver)
4599 talloc_free(driver);
4604 /****************************************************************************
4605 Determine whether or not a particular driver is currently assigned
4607 ****************************************************************************/
4609 bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r)
4612 int n_services = lp_numservices();
4613 NT_PRINTER_INFO_LEVEL *printer = NULL;
4614 bool in_use = False;
4620 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4622 /* loop through the printers.tdb and check for the drivername */
4624 for (snum=0; snum<n_services && !in_use; snum++) {
4625 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4628 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4631 if (strequal(r->driver_name, printer->info_2->drivername))
4634 free_a_printer( &printer, 2 );
4637 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4640 struct spoolss_DriverInfo8 *d;
4643 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
4645 /* we can still remove the driver if there is one of
4646 "Windows NT x86" version 2 or 3 left */
4648 if (!strequal("Windows NT x86", r->architecture)) {
4649 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION);
4652 switch (r->version) {
4654 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3);
4657 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2);
4660 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4662 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4667 /* now check the error code */
4669 if ( W_ERROR_IS_OK(werr) ) {
4670 /* it's ok to remove the driver, we have other architctures left */
4672 free_a_printer_driver(d);
4676 /* report that the driver is not in use by default */
4682 /**********************************************************************
4683 Check to see if a ogiven file is in use by *info
4684 *********************************************************************/
4686 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
4693 /* mz: skip files that are in the list but already deleted */
4694 if (!file || !file[0]) {
4698 if (strequal(file, info->driver_path))
4701 if (strequal(file, info->data_file))
4704 if (strequal(file, info->config_file))
4707 if (strequal(file, info->help_file))
4710 /* see of there are any dependent files to examine */
4712 if (!info->dependent_files)
4715 while (info->dependent_files[i] && *info->dependent_files[i]) {
4716 if (strequal(file, info->dependent_files[i]))
4725 /**********************************************************************
4726 Utility function to remove the dependent file pointed to by the
4727 input parameter from the list
4728 *********************************************************************/
4730 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
4733 /* bump everything down a slot */
4735 while (files && files[idx+1]) {
4736 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
4745 /**********************************************************************
4746 Check if any of the files used by src are also used by drv
4747 *********************************************************************/
4749 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
4750 struct spoolss_DriverInfo8 *src,
4751 const struct spoolss_DriverInfo8 *drv)
4753 bool in_use = False;
4759 /* check each file. Remove it from the src structure if it overlaps */
4761 if (drv_file_in_use(src->driver_path, drv)) {
4763 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
4764 src->driver_path = talloc_strdup(mem_ctx, "");
4765 if (!src->driver_path) { return false; }
4768 if (drv_file_in_use(src->data_file, drv)) {
4770 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
4771 src->data_file = talloc_strdup(mem_ctx, "");
4772 if (!src->data_file) { return false; }
4775 if (drv_file_in_use(src->config_file, drv)) {
4777 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
4778 src->config_file = talloc_strdup(mem_ctx, "");
4779 if (!src->config_file) { return false; }
4782 if (drv_file_in_use(src->help_file, drv)) {
4784 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
4785 src->help_file = talloc_strdup(mem_ctx, "");
4786 if (!src->help_file) { return false; }
4789 /* are there any dependentfiles to examine? */
4791 if (!src->dependent_files)
4794 while (src->dependent_files[i] && *src->dependent_files[i]) {
4795 if (drv_file_in_use(src->dependent_files[i], drv)) {
4797 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
4798 trim_dependent_file(mem_ctx, src->dependent_files, i);
4806 /****************************************************************************
4807 Determine whether or not a particular driver files are currently being
4808 used by any other driver.
4810 Return value is True if any files were in use by other drivers
4811 and False otherwise.
4813 Upon return, *info has been modified to only contain the driver files
4814 which are not in use
4818 This needs to check all drivers to ensure that all files in use
4819 have been removed from *info, not just the ones in the first
4821 ****************************************************************************/
4823 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
4824 struct spoolss_DriverInfo8 *info)
4829 fstring *list = NULL;
4830 struct spoolss_DriverInfo8 *driver;
4831 bool in_use = false;
4836 version = info->version;
4838 /* loop over all driver versions */
4840 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4842 /* get the list of drivers */
4845 ndrivers = get_ntdrivers(&list, info->architecture, version);
4847 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4848 ndrivers, info->architecture, version));
4850 /* check each driver for overlap in files */
4852 for (i=0; i<ndrivers; i++) {
4853 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4857 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, list[i], info->architecture, version))) {
4862 /* check if d2 uses any files from d1 */
4863 /* only if this is a different driver than the one being deleted */
4865 if (!strequal(info->driver_name, driver->driver_name)) {
4866 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
4867 /* mz: Do not instantly return -
4868 * we need to ensure this file isn't
4869 * also in use by other drivers. */
4874 free_a_printer_driver(driver);
4879 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4884 static NTSTATUS driver_unlink_internals(connection_struct *conn,
4887 struct smb_filename *smb_fname = NULL;
4890 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
4892 if (!NT_STATUS_IS_OK(status)) {
4896 status = unlink_internals(conn, NULL, 0, smb_fname, false);
4898 TALLOC_FREE(smb_fname);
4902 /****************************************************************************
4903 Actually delete the driver files. Make sure that
4904 printer_driver_files_in_use() return False before calling
4906 ****************************************************************************/
4908 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
4909 const struct spoolss_DriverInfo8 *r)
4914 connection_struct *conn;
4917 fstring printdollar;
4918 int printdollar_snum;
4925 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
4926 r->driver_name, r->version));
4928 fstrcpy(printdollar, "print$");
4930 printdollar_snum = find_service(printdollar);
4931 if (printdollar_snum == -1) {
4935 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
4936 lp_pathname(printdollar_snum),
4937 rpc_pipe->server_info, &oldcwd);
4938 if (!NT_STATUS_IS_OK(nt_status)) {
4939 DEBUG(0,("delete_driver_files: create_conn_struct "
4940 "returned %s\n", nt_errstr(nt_status)));
4944 if ( !CAN_WRITE(conn) ) {
4945 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4949 /* now delete the files; must strip the '\print$' string from
4952 if (r->driver_path && r->driver_path[0]) {
4953 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
4955 DEBUG(10,("deleting driverfile [%s]\n", s));
4956 driver_unlink_internals(conn, file);
4960 if (r->config_file && r->config_file[0]) {
4961 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
4963 DEBUG(10,("deleting configfile [%s]\n", s));
4964 driver_unlink_internals(conn, file);
4968 if (r->data_file && r->data_file[0]) {
4969 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
4971 DEBUG(10,("deleting datafile [%s]\n", s));
4972 driver_unlink_internals(conn, file);
4976 if (r->help_file && r->help_file[0]) {
4977 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
4979 DEBUG(10,("deleting helpfile [%s]\n", s));
4980 driver_unlink_internals(conn, file);
4984 /* check if we are done removing files */
4986 if (r->dependent_files) {
4987 while (r->dependent_files[i] && r->dependent_files[i][0]) {
4990 /* bypass the "\print$" portion of the path */
4992 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
4994 DEBUG(10,("deleting dependent file [%s]\n", file));
4995 driver_unlink_internals(conn, file);
5007 vfs_ChDir(conn, oldcwd);
5013 /****************************************************************************
5014 Remove a printer driver from the TDB. This assumes that the the driver was
5015 previously looked up.
5016 ***************************************************************************/
5018 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5019 const struct spoolss_DriverInfo8 *r,
5020 uint32 version, bool delete_files )
5026 /* delete the tdb data first */
5028 arch = get_short_archi(r->architecture);
5030 return WERR_UNKNOWN_PRINTER_DRIVER;
5032 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5033 arch, version, r->driver_name) < 0) {
5037 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5038 key, delete_files ? "TRUE" : "FALSE" ));
5040 /* check if the driver actually exists for this environment */
5042 dbuf = tdb_fetch_bystring( tdb_drivers, key );
5044 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5046 return WERR_UNKNOWN_PRINTER_DRIVER;
5049 SAFE_FREE( dbuf.dptr );
5051 /* ok... the driver exists so the delete should return success */
5053 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5054 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5056 return WERR_ACCESS_DENIED;
5060 * now delete any associated files if delete_files == True
5061 * even if this part failes, we return succes because the
5062 * driver doesn not exist any more
5066 delete_driver_files(rpc_pipe, r);
5068 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5074 /****************************************************************************
5075 Store a security desc for a printer.
5076 ****************************************************************************/
5078 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
5080 struct sec_desc_buf *new_secdesc_ctr = NULL;
5081 struct sec_desc_buf *old_secdesc_ctr = NULL;
5082 TALLOC_CTX *mem_ctx = NULL;
5089 mem_ctx = talloc_init("nt_printing_setsec");
5090 if (mem_ctx == NULL)
5093 /* The old owner and group sids of the security descriptor are not
5094 present when new ACEs are added or removed by changing printer
5095 permissions through NT. If they are NULL in the new security
5096 descriptor then copy them over from the old one. */
5098 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5099 struct dom_sid *owner_sid, *group_sid;
5100 struct security_acl *dacl, *sacl;
5101 struct security_descriptor *psd = NULL;
5104 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5105 status = WERR_NOMEM;
5109 /* Pick out correct owner and group sids */
5111 owner_sid = secdesc_ctr->sd->owner_sid ?
5112 secdesc_ctr->sd->owner_sid :
5113 old_secdesc_ctr->sd->owner_sid;
5115 group_sid = secdesc_ctr->sd->group_sid ?
5116 secdesc_ctr->sd->group_sid :
5117 old_secdesc_ctr->sd->group_sid;
5119 dacl = secdesc_ctr->sd->dacl ?
5120 secdesc_ctr->sd->dacl :
5121 old_secdesc_ctr->sd->dacl;
5123 sacl = secdesc_ctr->sd->sacl ?
5124 secdesc_ctr->sd->sacl :
5125 old_secdesc_ctr->sd->sacl;
5127 /* Make a deep copy of the security descriptor */
5129 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5130 owner_sid, group_sid,
5136 status = WERR_NOMEM;
5140 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5143 if (!new_secdesc_ctr) {
5144 new_secdesc_ctr = secdesc_ctr;
5147 /* Store the security descriptor in a tdb */
5149 nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5150 &blob.data, &blob.length);
5151 if (!NT_STATUS_IS_OK(nt_status)) {
5152 status = ntstatus_to_werror(nt_status);
5156 kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5158 dbuf.dptr = (unsigned char *)blob.data;
5159 dbuf.dsize = blob.length;
5161 if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5164 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5165 status = WERR_BADFUNC;
5168 /* Free malloc'ed memory */
5169 talloc_free(blob.data);
5174 talloc_destroy(mem_ctx);
5178 /****************************************************************************
5179 Construct a default security descriptor buffer for a printer.
5180 ****************************************************************************/
5182 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
5184 struct security_ace ace[7]; /* max number of ace entries */
5187 struct security_acl *psa = NULL;
5188 struct sec_desc_buf *sdb = NULL;
5189 struct security_descriptor *psd = NULL;
5190 struct dom_sid adm_sid;
5193 /* Create an ACE where Everyone is allowed to print */
5195 sa = PRINTER_ACE_PRINT;
5196 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5197 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5199 /* Add the domain admins group if we are a DC */
5202 struct dom_sid domadmins_sid;
5204 sid_compose(&domadmins_sid, get_global_sam_sid(),
5207 sa = PRINTER_ACE_FULL_CONTROL;
5208 init_sec_ace(&ace[i++], &domadmins_sid,
5209 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5210 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5211 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5212 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5214 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5215 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
5217 sa = PRINTER_ACE_FULL_CONTROL;
5218 init_sec_ace(&ace[i++], &adm_sid,
5219 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5220 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5221 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5222 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5225 /* add BUILTIN\Administrators as FULL CONTROL */
5227 sa = PRINTER_ACE_FULL_CONTROL;
5228 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5229 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5230 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5231 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5232 SEC_ACE_TYPE_ACCESS_ALLOWED,
5233 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5235 /* add BUILTIN\Print Operators as FULL CONTROL */
5237 sa = PRINTER_ACE_FULL_CONTROL;
5238 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
5239 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5240 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5241 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
5242 SEC_ACE_TYPE_ACCESS_ALLOWED,
5243 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5245 /* Make the security descriptor owned by the BUILTIN\Administrators */
5247 /* The ACL revision number in rpc_secdesc.h differs from the one
5248 created by NT when setting ACE entries in printer
5249 descriptors. NT4 complains about the property being edited by a
5252 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5253 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
5254 &global_sid_Builtin_Administrators,
5255 &global_sid_Builtin_Administrators,
5256 NULL, psa, &sd_size);
5260 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5264 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5266 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5267 (unsigned int)sd_size));
5272 /****************************************************************************
5273 Get a security desc for a printer.
5274 ****************************************************************************/
5276 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
5284 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5285 sharename = temp + 1;
5288 /* Fetch security descriptor from tdb */
5290 kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5292 dbuf = tdb_fetch(tdb_printers, kbuf);
5295 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5297 SAFE_FREE(dbuf.dptr);
5299 if (NT_STATUS_IS_OK(status)) {
5304 *secdesc_ctr = construct_default_printer_sdb(ctx);
5305 if (!*secdesc_ctr) {
5309 status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5310 &blob.data, &blob.length);
5311 if (NT_STATUS_IS_OK(status)) {
5312 dbuf.dptr = (unsigned char *)blob.data;
5313 dbuf.dsize = blob.length;
5314 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5315 talloc_free(blob.data);
5318 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5319 this security descriptor has been created when winbindd was
5320 down. Take ownership of security descriptor. */
5322 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5323 struct dom_sid owner_sid;
5325 /* Change sd owner to workgroup administrator */
5327 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5328 struct sec_desc_buf *new_secdesc_ctr = NULL;
5329 struct security_descriptor *psd = NULL;
5334 sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
5336 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5338 (*secdesc_ctr)->sd->group_sid,
5339 (*secdesc_ctr)->sd->sacl,
5340 (*secdesc_ctr)->sd->dacl,
5347 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5348 if (!new_secdesc_ctr) {
5352 /* Swap with other one */
5354 *secdesc_ctr = new_secdesc_ctr;
5358 nt_printing_setsec(sharename, *secdesc_ctr);
5362 if (DEBUGLEVEL >= 10) {
5363 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
5366 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5367 sharename, the_acl->num_aces));
5369 for (i = 0; i < the_acl->num_aces; i++) {
5370 DEBUG(10, ("%s %d %d 0x%08x\n",
5371 sid_string_dbg(&the_acl->aces[i].trustee),
5372 the_acl->aces[i].type, the_acl->aces[i].flags,
5373 the_acl->aces[i].access_mask));
5382 1: level not implemented
5383 2: file doesn't exist
5384 3: can't allocate memory
5385 4: can't free memory
5386 5: non existant struct
5390 A printer and a printer driver are 2 different things.
5391 NT manages them separatelly, Samba does the same.
5392 Why ? Simply because it's easier and it makes sense !
5394 Now explanation: You have 3 printers behind your samba server,
5395 2 of them are the same make and model (laser A and B). But laser B
5396 has an 3000 sheet feeder and laser A doesn't such an option.
5397 Your third printer is an old dot-matrix model for the accounting :-).
5399 If the /usr/local/samba/lib directory (default dir), you will have
5400 5 files to describe all of this.
5402 3 files for the printers (1 by printer):
5405 NTprinter_accounting
5406 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5407 NTdriver_printer model X
5408 NTdriver_printer model Y
5410 jfm: I should use this comment for the text file to explain
5411 same thing for the forms BTW.
5412 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5416 /* Convert generic access rights to printer object specific access rights.
5417 It turns out that NT4 security descriptors use generic access rights and
5418 NT5 the object specific ones. */
5420 void map_printer_permissions(struct security_descriptor *sd)
5424 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5425 se_map_generic(&sd->dacl->aces[i].access_mask,
5426 &printer_generic_mapping);
5430 void map_job_permissions(struct security_descriptor *sd)
5434 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5435 se_map_generic(&sd->dacl->aces[i].access_mask,
5436 &job_generic_mapping);
5441 /****************************************************************************
5442 Check a user has permissions to perform the given operation. We use the
5443 permission constants defined in include/rpc_spoolss.h to check the various
5444 actions we perform when checking printer access.
5446 PRINTER_ACCESS_ADMINISTER:
5447 print_queue_pause, print_queue_resume, update_printer_sec,
5448 update_printer, spoolss_addprinterex_level_2,
5449 _spoolss_setprinterdata
5454 JOB_ACCESS_ADMINISTER:
5455 print_job_delete, print_job_pause, print_job_resume,
5458 Try access control in the following order (for performance reasons):
5459 1) root and SE_PRINT_OPERATOR can do anything (easy check)
5460 2) check security descriptor (bit comparisons in memory)
5461 3) "printer admins" (may result in numerous calls to winbind)
5463 ****************************************************************************/
5464 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5467 struct spoolss_security_descriptor *secdesc = NULL;
5468 uint32 access_granted;
5473 TALLOC_CTX *mem_ctx = NULL;
5474 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5476 /* If user is NULL then use the current_user structure */
5478 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5480 if (server_info->utok.uid == sec_initial_uid()
5481 || user_has_privileges(server_info->ptok, &se_printop ) ) {
5485 /* Get printer name */
5487 pname = lp_printername(snum);
5489 if (!pname || !*pname) {
5494 /* Get printer security descriptor */
5496 if(!(mem_ctx = talloc_init("print_access_check"))) {
5501 result = winreg_get_printer_secdesc(mem_ctx,
5505 if (!W_ERROR_IS_OK(result)) {
5506 talloc_destroy(mem_ctx);
5511 if (access_type == JOB_ACCESS_ADMINISTER) {
5512 struct spoolss_security_descriptor *parent_secdesc = secdesc;
5514 /* Create a child security descriptor to check permissions
5515 against. This is because print jobs are child objects
5516 objects of a printer. */
5517 status = se_create_child_secdesc(mem_ctx,
5521 parent_secdesc->owner_sid,
5522 parent_secdesc->group_sid,
5524 if (!NT_STATUS_IS_OK(status)) {
5525 talloc_destroy(mem_ctx);
5526 errno = map_errno_from_nt_status(status);
5530 map_job_permissions(secdesc);
5532 map_printer_permissions(secdesc);
5536 status = se_access_check(secdesc, server_info->ptok, access_type,
5539 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5541 /* see if we need to try the printer admin list */
5543 if (!NT_STATUS_IS_OK(status) &&
5544 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5545 server_info->info3->base.domain.string,
5546 NULL, server_info->ptok,
5547 lp_printer_admin(snum)))) {
5548 talloc_destroy(mem_ctx);
5552 talloc_destroy(mem_ctx);
5554 if (!NT_STATUS_IS_OK(status)) {
5558 return NT_STATUS_IS_OK(status);
5561 /****************************************************************************
5562 Check the time parameters allow a print operation.
5563 *****************************************************************************/
5565 bool print_time_access_check(const char *servicename)
5567 NT_PRINTER_INFO_LEVEL *printer = NULL;
5569 time_t now = time(NULL);
5573 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5576 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5580 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5582 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5585 free_a_printer(&printer, 2);
5593 /****************************************************************************
5594 Fill in the servername sent in the _spoolss_open_printer_ex() call
5595 ****************************************************************************/
5597 char* get_server_name( Printer_entry *printer )
5599 return printer->servername;