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 #include "../rpc_server/srv_spoolss_util.h"
32 static TDB_CONTEXT *tdb_forms; /* used for forms files */
33 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
34 static TDB_CONTEXT *tdb_printers; /* used for printers files */
36 #define FORMS_PREFIX "FORMS/"
37 #define DRIVERS_PREFIX "DRIVERS/"
38 #define PRINTERS_PREFIX "PRINTERS/"
39 #define SECDESC_PREFIX "SECDESC/"
40 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
42 #define NTDRIVERS_DATABASE_VERSION_1 1
43 #define NTDRIVERS_DATABASE_VERSION_2 2
44 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
45 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
46 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
48 /* Map generic permissions to printer object specific permissions */
50 const struct generic_mapping printer_generic_mapping = {
57 const struct standard_mapping printer_std_mapping = {
64 /* Map generic permissions to print server object specific permissions */
66 const struct generic_mapping printserver_generic_mapping = {
73 const struct generic_mapping printserver_std_mapping = {
80 /* Map generic permissions to job object specific permissions */
82 const struct generic_mapping job_generic_mapping = {
89 /* We need one default form to support our default printer. Msoft adds the
90 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
91 array index). Letter is always first, so (for the current code) additions
92 always put things in the correct order. */
93 static const nt_forms_struct default_forms[] = {
94 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
95 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
96 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
97 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
98 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
99 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
100 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
101 {"A0",0x1,0xcd528,0x122488,0x0,0x0,0xcd528,0x122488},
102 {"A1",0x1,0x91050,0xcd528,0x0,0x0,0x91050,0xcd528},
103 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
104 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
105 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
106 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
107 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
108 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
109 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
110 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
111 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
112 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
113 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
114 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
115 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
116 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
117 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
118 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
119 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
120 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
121 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
122 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
123 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
124 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
125 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
126 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
127 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
128 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
129 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
130 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
131 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
132 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
133 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
134 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
135 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
136 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
137 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
138 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
139 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
140 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
141 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
142 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
143 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
144 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
145 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
146 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
147 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
148 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
149 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
150 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
151 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
152 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
153 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
154 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
155 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
156 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
157 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
158 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
159 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
160 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
161 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
162 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
163 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
164 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
165 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
166 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
167 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
168 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
169 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
170 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
171 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
172 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
173 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
174 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
175 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
176 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
177 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
178 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
179 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
180 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
181 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
182 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
183 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
184 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
185 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
186 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
187 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
188 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
189 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
190 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
191 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
192 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
193 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
194 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
195 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
196 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
197 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
198 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
199 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
200 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
201 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
202 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
203 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
204 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
205 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
206 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
207 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
208 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
209 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
210 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
211 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
212 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
213 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
216 static const struct print_architecture_table_node archi_table[]= {
218 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
219 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
220 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
221 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
222 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
223 {"Windows IA64", SPL_ARCH_IA64, 3 },
224 {"Windows x64", SPL_ARCH_X64, 3 },
229 /****************************************************************************
230 generate a new TDB_DATA key for storing a printer
231 ****************************************************************************/
233 static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
239 fstrcpy(share, sharename);
242 keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
243 key = string_term_tdb_data(keystr ? keystr : "");
248 /****************************************************************************
249 generate a new TDB_DATA key for storing a printer security descriptor
250 ****************************************************************************/
252 static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
253 const char* sharename )
259 fstrcpy(share, sharename );
262 keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
263 key = string_term_tdb_data(keystr ? keystr : "");
268 /****************************************************************************
269 ****************************************************************************/
271 static bool upgrade_to_version_3(void)
273 TDB_DATA kbuf, newkey, dbuf;
275 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
277 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
278 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
280 dbuf = tdb_fetch(tdb_drivers, kbuf);
282 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
283 DEBUG(0,("upgrade_to_version_3:moving form\n"));
284 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
285 SAFE_FREE(dbuf.dptr);
286 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
289 if (tdb_delete(tdb_drivers, kbuf) != 0) {
290 SAFE_FREE(dbuf.dptr);
291 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
296 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
297 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
298 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
299 SAFE_FREE(dbuf.dptr);
300 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
303 if (tdb_delete(tdb_drivers, kbuf) != 0) {
304 SAFE_FREE(dbuf.dptr);
305 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
310 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
311 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
312 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
313 SAFE_FREE(dbuf.dptr);
314 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
317 if (tdb_delete(tdb_drivers, kbuf) != 0) {
318 SAFE_FREE(dbuf.dptr);
319 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
324 SAFE_FREE(dbuf.dptr);
330 /*******************************************************************
331 Fix an issue with security descriptors. Printer sec_desc must
332 use more than the generic bits that were previously used
333 in <= 3.0.14a. They must also have a owner and group SID assigned.
334 Otherwise, any printers than have been migrated to a Windows
335 host using printmig.exe will not be accessible.
336 *******************************************************************/
338 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
339 TDB_DATA data, void *state )
342 struct sec_desc_buf *sd_orig = NULL;
343 struct sec_desc_buf *sd_new, *sd_store;
344 struct security_descriptor *sec, *new_sec;
345 TALLOC_CTX *ctx = state;
350 if (!data.dptr || data.dsize == 0) {
354 if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
358 /* upgrade the security descriptor */
360 status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
361 if (!NT_STATUS_IS_OK(status)) {
362 /* delete bad entries */
363 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
364 (const char *)key.dptr ));
365 tdb_delete( tdb_printers, key );
374 /* is this even valid? */
380 /* update access masks */
382 for ( i=0; i<sec->dacl->num_aces; i++ ) {
383 switch ( sec->dacl->aces[i].access_mask ) {
384 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
385 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
388 case GENERIC_ALL_ACCESS:
389 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
392 case READ_CONTROL_ACCESS:
393 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
395 default: /* no change */
400 /* create a new struct security_descriptor with the appropriate owner and group SIDs */
402 new_sec = make_sec_desc( ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
403 &global_sid_Builtin_Administrators,
404 &global_sid_Builtin_Administrators,
405 NULL, NULL, &size_new_sec );
409 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
414 if ( !(sd_store = sec_desc_merge_buf( ctx, sd_new, sd_orig )) ) {
415 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
421 sd_size = ndr_size_security_descriptor(sd_store->sd, 0)
422 + sizeof(struct sec_desc_buf);
424 status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
425 if (!NT_STATUS_IS_OK(status)) {
426 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
430 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
432 /* 0 to continue and non-zero to stop traversal */
434 return (result == -1);
437 /*******************************************************************
438 *******************************************************************/
440 static bool upgrade_to_version_4(void)
445 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
447 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
450 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
452 talloc_destroy( ctx );
454 return ( result != -1 );
457 /*******************************************************************
458 Fix an issue with security descriptors. Printer sec_desc must
459 use more than the generic bits that were previously used
460 in <= 3.0.14a. They must also have a owner and group SID assigned.
461 Otherwise, any printers than have been migrated to a Windows
462 host using printmig.exe will not be accessible.
463 *******************************************************************/
465 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
466 TDB_DATA data, void *state )
468 TALLOC_CTX *ctx = talloc_tos();
471 if (!data.dptr || data.dsize == 0)
474 /* upgrade printer records and security descriptors */
476 if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
477 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
479 else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
480 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
483 /* ignore this record */
487 /* delete the original record and store under the normalized key */
489 if ( tdb_delete( the_tdb, key ) != 0 ) {
490 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
495 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
496 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
504 /*******************************************************************
505 *******************************************************************/
507 static bool upgrade_to_version_5(void)
512 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
514 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
517 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
519 talloc_destroy( ctx );
521 return ( result != -1 );
524 /****************************************************************************
525 Open the NT printing tdbs. Done once before fork().
526 ****************************************************************************/
528 bool nt_printing_init(struct messaging_context *msg_ctx)
530 const char *vstring = "INFO/version";
534 if ( tdb_drivers && tdb_printers && tdb_forms )
538 tdb_close(tdb_drivers);
539 tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
541 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
542 state_path("ntdrivers.tdb"), strerror(errno) ));
547 tdb_close(tdb_printers);
548 tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
550 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
551 state_path("ntprinters.tdb"), strerror(errno) ));
556 tdb_close(tdb_forms);
557 tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
559 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
560 state_path("ntforms.tdb"), strerror(errno) ));
564 /* handle a Samba upgrade */
566 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
568 DEBUG(10, ("Fresh database\n"));
569 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
570 vers_id = NTDRIVERS_DATABASE_VERSION_5;
573 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
575 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
576 if (!upgrade_to_version_3())
578 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
579 vers_id = NTDRIVERS_DATABASE_VERSION_3;
582 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
583 /* Written on a bigendian machine with old fetch_int code. Save as le. */
584 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
585 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
586 vers_id = NTDRIVERS_DATABASE_VERSION_3;
589 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
590 if ( !upgrade_to_version_4() )
592 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
593 vers_id = NTDRIVERS_DATABASE_VERSION_4;
596 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
597 if ( !upgrade_to_version_5() )
599 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
600 vers_id = NTDRIVERS_DATABASE_VERSION_5;
604 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
605 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
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 Function to do the mapping between the long architecture name and
966 ****************************************************************************/
968 const char *get_short_archi(const char *long_archi)
972 DEBUG(107,("Getting architecture dependant directory\n"));
975 } while ( (archi_table[i].long_archi!=NULL ) &&
976 StrCaseCmp(long_archi, archi_table[i].long_archi) );
978 if (archi_table[i].long_archi==NULL) {
979 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
983 /* this might be client code - but shouldn't this be an fstrcpy etc? */
985 DEBUGADD(108,("index: [%d]\n", i));
986 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
987 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
989 return archi_table[i].short_archi;
992 /****************************************************************************
993 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
994 There are two case to be covered here: PE (Portable Executable) and NE (New
995 Executable) files. Both files support the same INFO structure, but PE files
996 store the signature in unicode, and NE files store it as !unicode.
997 returns -1 on error, 1 on version info found, and 0 on no version info found.
998 ****************************************************************************/
1000 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1006 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1007 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1008 fname, DOS_HEADER_SIZE));
1012 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1013 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1014 fname, (unsigned long)byte_count));
1015 goto no_version_info;
1018 /* Is this really a DOS header? */
1019 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1020 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1021 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1022 goto no_version_info;
1025 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1026 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1027 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1029 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1030 goto no_version_info;
1033 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1034 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1035 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1036 fname, (unsigned long)byte_count));
1037 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1038 goto no_version_info;
1041 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1042 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1043 unsigned int num_sections;
1044 unsigned int section_table_bytes;
1046 /* Just skip over optional header to get to section table */
1047 if (SMB_VFS_LSEEK(fsp,
1048 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1049 SEEK_CUR) == (SMB_OFF_T)-1) {
1050 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1055 /* get the section table */
1056 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1057 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1058 if (section_table_bytes == 0)
1062 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1063 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1064 fname, section_table_bytes));
1068 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1069 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1070 fname, (unsigned long)byte_count));
1074 /* Iterate the section table looking for the resource section ".rsrc" */
1075 for (i = 0; i < num_sections; i++) {
1076 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1078 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1079 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1080 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1082 if (section_bytes == 0)
1086 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1087 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1088 fname, section_bytes));
1092 /* Seek to the start of the .rsrc section info */
1093 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1094 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1099 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1100 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1101 fname, (unsigned long)byte_count));
1105 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1108 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1109 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1110 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1111 /* Align to next long address */
1112 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1114 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1115 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1116 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1118 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1119 fname, *major, *minor,
1120 (*major>>16)&0xffff, *major&0xffff,
1121 (*minor>>16)&0xffff, *minor&0xffff));
1130 /* Version info not found, fall back to origin date/time */
1131 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1135 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1136 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1137 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1138 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1139 /* At this point, we assume the file is in error. It still could be somthing
1140 * else besides a NE file, but it unlikely at this point. */
1144 /* Allocate a bit more space to speed up things */
1146 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1147 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1148 fname, PE_HEADER_SIZE));
1152 /* This is a HACK! I got tired of trying to sort through the messy
1153 * 'NE' file format. If anyone wants to clean this up please have at
1154 * it, but this works. 'NE' files will eventually fade away. JRR */
1155 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1156 /* Cover case that should not occur in a well formed 'NE' .dll file */
1157 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1159 for(i=0; i<byte_count; i++) {
1160 /* Fast skip past data that can't possibly match */
1161 if (buf[i] != 'V') continue;
1163 /* Potential match data crosses buf boundry, move it to beginning
1164 * of buf, and fill the buf with as much as it will hold. */
1165 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1168 memcpy(buf, &buf[i], byte_count-i);
1169 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1170 (byte_count-i))) < 0) {
1172 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1177 byte_count = bc + (byte_count - i);
1178 if (byte_count<VS_VERSION_INFO_SIZE) break;
1183 /* Check that the full signature string and the magic number that
1184 * follows exist (not a perfect solution, but the chances that this
1185 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1186 * twice, as it is simpler to read the code. */
1187 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1188 /* Compute skip alignment to next long address */
1189 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1190 sizeof(VS_SIGNATURE)) & 3;
1191 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1193 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1194 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1195 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1196 fname, *major, *minor,
1197 (*major>>16)&0xffff, *major&0xffff,
1198 (*minor>>16)&0xffff, *minor&0xffff));
1205 /* Version info not found, fall back to origin date/time */
1206 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1211 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1212 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1213 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1224 /****************************************************************************
1225 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1226 share one or more files. During the MS installation process files are checked
1227 to insure that only a newer version of a shared file is installed over an
1228 older version. There are several possibilities for this comparison. If there
1229 is no previous version, the new one is newer (obviously). If either file is
1230 missing the version info structure, compare the creation date (on Unix use
1231 the modification date). Otherwise chose the numerically larger version number.
1232 ****************************************************************************/
1234 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1236 bool use_version = true;
1240 time_t new_create_time;
1244 time_t old_create_time;
1246 struct smb_filename *smb_fname = NULL;
1247 files_struct *fsp = NULL;
1253 SET_STAT_INVALID(st);
1254 new_create_time = (time_t)0;
1255 old_create_time = (time_t)0;
1257 /* Get file version info (if available) for previous file (if it exists) */
1258 status = driver_unix_convert(conn, old_file, &smb_fname);
1259 if (!NT_STATUS_IS_OK(status)) {
1263 status = SMB_VFS_CREATE_FILE(
1266 0, /* root_dir_fid */
1267 smb_fname, /* fname */
1268 FILE_GENERIC_READ, /* access_mask */
1269 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1270 FILE_OPEN, /* create_disposition*/
1271 0, /* create_options */
1272 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1273 INTERNAL_OPEN_ONLY, /* oplock_request */
1274 0, /* allocation_size */
1275 0, /* private_flags */
1281 if (!NT_STATUS_IS_OK(status)) {
1282 /* Old file not found, so by definition new file is in fact newer */
1283 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
1284 "errno = %d\n", smb_fname_str_dbg(smb_fname),
1290 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1296 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1298 use_version = false;
1299 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1302 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1303 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1304 (long)old_create_time));
1307 close_file(NULL, fsp, NORMAL_CLOSE);
1310 /* Get file version info (if available) for new file */
1311 status = driver_unix_convert(conn, new_file, &smb_fname);
1312 if (!NT_STATUS_IS_OK(status)) {
1316 status = SMB_VFS_CREATE_FILE(
1319 0, /* root_dir_fid */
1320 smb_fname, /* fname */
1321 FILE_GENERIC_READ, /* access_mask */
1322 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1323 FILE_OPEN, /* create_disposition*/
1324 0, /* create_options */
1325 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1326 INTERNAL_OPEN_ONLY, /* oplock_request */
1327 0, /* allocation_size */
1328 0, /* private_flags */
1334 if (!NT_STATUS_IS_OK(status)) {
1335 /* New file not found, this shouldn't occur if the caller did its job */
1336 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
1337 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
1341 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1347 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1349 use_version = false;
1350 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1353 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1354 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1355 (long)new_create_time));
1358 close_file(NULL, fsp, NORMAL_CLOSE);
1361 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1362 /* Compare versions and choose the larger version number */
1363 if (new_major > old_major ||
1364 (new_major == old_major && new_minor > old_minor)) {
1366 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1371 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1377 /* Compare modification time/dates and choose the newest time/date */
1378 if (new_create_time > old_create_time) {
1379 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1384 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1392 close_file(NULL, fsp, NORMAL_CLOSE);
1395 TALLOC_FREE(smb_fname);
1399 /****************************************************************************
1400 Determine the correct cVersion associated with an architecture and driver
1401 ****************************************************************************/
1402 static uint32 get_correct_cversion(struct pipes_struct *p,
1403 const char *architecture,
1404 const char *driverpath_in,
1409 struct smb_filename *smb_fname = NULL;
1410 char *driverpath = NULL;
1411 files_struct *fsp = NULL;
1412 connection_struct *conn = NULL;
1415 fstring printdollar;
1416 int printdollar_snum;
1418 *perr = WERR_INVALID_PARAM;
1420 /* If architecture is Windows 95/98/ME, the version is always 0. */
1421 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1422 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1427 /* If architecture is Windows x64, the version is always 3. */
1428 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1429 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1434 fstrcpy(printdollar, "print$");
1436 printdollar_snum = find_service(printdollar);
1437 if (printdollar_snum == -1) {
1438 *perr = WERR_NO_SUCH_SHARE;
1442 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1443 lp_pathname(printdollar_snum),
1444 p->server_info, &oldcwd);
1445 if (!NT_STATUS_IS_OK(nt_status)) {
1446 DEBUG(0,("get_correct_cversion: create_conn_struct "
1447 "returned %s\n", nt_errstr(nt_status)));
1448 *perr = ntstatus_to_werror(nt_status);
1452 /* Open the driver file (Portable Executable format) and determine the
1453 * deriver the cversion. */
1454 driverpath = talloc_asprintf(talloc_tos(),
1463 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
1464 if (!NT_STATUS_IS_OK(nt_status)) {
1465 *perr = ntstatus_to_werror(nt_status);
1469 nt_status = vfs_file_exist(conn, smb_fname);
1470 if (!NT_STATUS_IS_OK(nt_status)) {
1471 *perr = WERR_BADFILE;
1475 status = SMB_VFS_CREATE_FILE(
1478 0, /* root_dir_fid */
1479 smb_fname, /* fname */
1480 FILE_GENERIC_READ, /* access_mask */
1481 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1482 FILE_OPEN, /* create_disposition*/
1483 0, /* create_options */
1484 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1485 INTERNAL_OPEN_ONLY, /* oplock_request */
1486 0, /* private_flags */
1487 0, /* allocation_size */
1493 if (!NT_STATUS_IS_OK(status)) {
1494 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1495 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1496 *perr = WERR_ACCESS_DENIED;
1503 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1504 if (ret == -1) goto error_exit;
1507 DEBUG(6,("get_correct_cversion: Version info not "
1509 smb_fname_str_dbg(smb_fname)));
1514 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1515 * for more details. Version in this case is not just the version of the
1516 * file, but the version in the sense of kernal mode (2) vs. user mode
1517 * (3) drivers. Other bits of the version fields are the version info.
1520 cversion = major & 0x0000ffff;
1522 case 2: /* WinNT drivers */
1523 case 3: /* Win2K drivers */
1527 DEBUG(6,("get_correct_cversion: cversion "
1528 "invalid [%s] cversion = %d\n",
1529 smb_fname_str_dbg(smb_fname),
1534 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1535 " = 0x%x minor = 0x%x\n",
1536 smb_fname_str_dbg(smb_fname), major, minor));
1539 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1540 smb_fname_str_dbg(smb_fname), cversion));
1547 TALLOC_FREE(smb_fname);
1549 close_file(NULL, fsp, NORMAL_CLOSE);
1552 vfs_ChDir(conn, oldcwd);
1555 if (cversion != -1) {
1561 /****************************************************************************
1562 ****************************************************************************/
1564 #define strip_driver_path(_mem_ctx, _element) do { \
1565 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1566 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1567 W_ERROR_HAVE_NO_MEMORY((_element)); \
1571 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1572 struct pipes_struct *rpc_pipe,
1573 const char *architecture,
1574 const char **driver_path,
1575 const char **data_file,
1576 const char **config_file,
1577 const char **help_file,
1578 struct spoolss_StringArray *dependent_files,
1581 const char *short_architecture;
1586 if (!*driver_path || !*data_file || !*config_file) {
1587 return WERR_INVALID_PARAM;
1590 /* clean up the driver name.
1591 * we can get .\driver.dll
1592 * or worse c:\windows\system\driver.dll !
1594 /* using an intermediate string to not have overlaping memcpy()'s */
1596 strip_driver_path(mem_ctx, *driver_path);
1597 strip_driver_path(mem_ctx, *data_file);
1598 strip_driver_path(mem_ctx, *config_file);
1600 strip_driver_path(mem_ctx, *help_file);
1603 if (dependent_files && dependent_files->string) {
1604 for (i=0; dependent_files->string[i]; i++) {
1605 strip_driver_path(mem_ctx, dependent_files->string[i]);
1609 short_architecture = get_short_archi(architecture);
1610 if (!short_architecture) {
1611 return WERR_UNKNOWN_PRINTER_DRIVER;
1614 /* jfm:7/16/2000 the client always sends the cversion=0.
1615 * The server should check which version the driver is by reading
1616 * the PE header of driver->driverpath.
1618 * For Windows 95/98 the version is 0 (so the value sent is correct)
1619 * For Windows NT (the architecture doesn't matter)
1620 * NT 3.1: cversion=0
1621 * NT 3.5/3.51: cversion=1
1626 *version = get_correct_cversion(rpc_pipe, short_architecture,
1627 *driver_path, &err);
1628 if (*version == -1) {
1635 /****************************************************************************
1636 ****************************************************************************/
1638 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1639 struct pipes_struct *rpc_pipe,
1640 struct spoolss_AddDriverInfoCtr *r)
1644 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
1645 r->info.info3->architecture,
1646 &r->info.info3->driver_path,
1647 &r->info.info3->data_file,
1648 &r->info.info3->config_file,
1649 &r->info.info3->help_file,
1650 r->info.info3->dependent_files,
1651 &r->info.info3->version);
1653 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
1654 r->info.info6->architecture,
1655 &r->info.info6->driver_path,
1656 &r->info.info6->data_file,
1657 &r->info.info6->config_file,
1658 &r->info.info6->help_file,
1659 r->info.info6->dependent_files,
1660 &r->info.info6->version);
1662 return WERR_NOT_SUPPORTED;
1666 /****************************************************************************
1667 This function sucks and should be replaced. JRA.
1668 ****************************************************************************/
1670 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1671 const struct spoolss_AddDriverInfo6 *src)
1673 dst->version = src->version;
1675 dst->driver_name = src->driver_name;
1676 dst->architecture = src->architecture;
1677 dst->driver_path = src->driver_path;
1678 dst->data_file = src->data_file;
1679 dst->config_file = src->config_file;
1680 dst->help_file = src->help_file;
1681 dst->monitor_name = src->monitor_name;
1682 dst->default_datatype = src->default_datatype;
1683 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1684 dst->dependent_files = src->dependent_files;
1687 /****************************************************************************
1688 ****************************************************************************/
1690 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1691 connection_struct *conn,
1692 const char *driver_file,
1693 const char *short_architecture,
1694 uint32_t driver_version,
1697 struct smb_filename *smb_fname_old = NULL;
1698 struct smb_filename *smb_fname_new = NULL;
1699 char *old_name = NULL;
1700 char *new_name = NULL;
1704 old_name = talloc_asprintf(mem_ctx, "%s/%s",
1705 short_architecture, driver_file);
1706 W_ERROR_HAVE_NO_MEMORY(old_name);
1708 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1709 short_architecture, driver_version, driver_file);
1710 if (new_name == NULL) {
1711 TALLOC_FREE(old_name);
1715 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1717 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1718 if (!NT_STATUS_IS_OK(status)) {
1723 /* Setup a synthetic smb_filename struct */
1724 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
1725 if (!smb_fname_new) {
1730 smb_fname_new->base_name = new_name;
1732 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1733 "'%s'\n", smb_fname_old->base_name,
1734 smb_fname_new->base_name));
1736 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1737 OPENX_FILE_EXISTS_TRUNCATE |
1738 OPENX_FILE_CREATE_IF_NOT_EXIST,
1741 if (!NT_STATUS_IS_OK(status)) {
1742 DEBUG(0,("move_driver_file_to_download_area: Unable "
1743 "to rename [%s] to [%s]: %s\n",
1744 smb_fname_old->base_name, new_name,
1745 nt_errstr(status)));
1746 ret = WERR_ACCESS_DENIED;
1753 TALLOC_FREE(smb_fname_old);
1754 TALLOC_FREE(smb_fname_new);
1758 WERROR move_driver_to_download_area(struct pipes_struct *p,
1759 struct spoolss_AddDriverInfoCtr *r,
1762 struct spoolss_AddDriverInfo3 *driver;
1763 struct spoolss_AddDriverInfo3 converted_driver;
1764 const char *short_architecture;
1765 struct smb_filename *smb_dname = NULL;
1766 char *new_dir = NULL;
1767 connection_struct *conn = NULL;
1770 TALLOC_CTX *ctx = talloc_tos();
1773 fstring printdollar;
1774 int printdollar_snum;
1780 driver = r->info.info3;
1783 convert_level_6_to_level3(&converted_driver, r->info.info6);
1784 driver = &converted_driver;
1787 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1788 return WERR_UNKNOWN_LEVEL;
1791 short_architecture = get_short_archi(driver->architecture);
1792 if (!short_architecture) {
1793 return WERR_UNKNOWN_PRINTER_DRIVER;
1796 fstrcpy(printdollar, "print$");
1798 printdollar_snum = find_service(printdollar);
1799 if (printdollar_snum == -1) {
1800 *perr = WERR_NO_SUCH_SHARE;
1801 return WERR_NO_SUCH_SHARE;
1804 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1805 lp_pathname(printdollar_snum),
1806 p->server_info, &oldcwd);
1807 if (!NT_STATUS_IS_OK(nt_status)) {
1808 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1809 "returned %s\n", nt_errstr(nt_status)));
1810 *perr = ntstatus_to_werror(nt_status);
1814 new_dir = talloc_asprintf(ctx,
1822 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1823 if (!NT_STATUS_IS_OK(nt_status)) {
1828 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1830 create_directory(conn, NULL, smb_dname);
1832 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1833 * listed for this driver which has already been moved, skip it (note:
1834 * drivers may list the same file name several times. Then check if the
1835 * file already exists in archi\version\, if so, check that the version
1836 * info (or time stamps if version info is unavailable) is newer (or the
1837 * date is later). If it is, move it to archi\version\filexxx.yyy.
1838 * Otherwise, delete the file.
1840 * If a file is not moved to archi\version\ because of an error, all the
1841 * rest of the 'unmoved' driver files are removed from archi\. If one or
1842 * more of the driver's files was already moved to archi\version\, it
1843 * potentially leaves the driver in a partially updated state. Version
1844 * trauma will most likely occur if an client attempts to use any printer
1845 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1846 * done is appropriate... later JRR
1849 DEBUG(5,("Moving files now !\n"));
1851 if (driver->driver_path && strlen(driver->driver_path)) {
1853 *perr = move_driver_file_to_download_area(ctx,
1855 driver->driver_path,
1859 if (!W_ERROR_IS_OK(*perr)) {
1860 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1867 if (driver->data_file && strlen(driver->data_file)) {
1868 if (!strequal(driver->data_file, driver->driver_path)) {
1870 *perr = move_driver_file_to_download_area(ctx,
1876 if (!W_ERROR_IS_OK(*perr)) {
1877 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1885 if (driver->config_file && strlen(driver->config_file)) {
1886 if (!strequal(driver->config_file, driver->driver_path) &&
1887 !strequal(driver->config_file, driver->data_file)) {
1889 *perr = move_driver_file_to_download_area(ctx,
1891 driver->config_file,
1895 if (!W_ERROR_IS_OK(*perr)) {
1896 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1904 if (driver->help_file && strlen(driver->help_file)) {
1905 if (!strequal(driver->help_file, driver->driver_path) &&
1906 !strequal(driver->help_file, driver->data_file) &&
1907 !strequal(driver->help_file, driver->config_file)) {
1909 *perr = move_driver_file_to_download_area(ctx,
1915 if (!W_ERROR_IS_OK(*perr)) {
1916 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1924 if (driver->dependent_files && driver->dependent_files->string) {
1925 for (i=0; driver->dependent_files->string[i]; i++) {
1926 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1927 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1928 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1929 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1931 for (j=0; j < i; j++) {
1932 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1937 *perr = move_driver_file_to_download_area(ctx,
1939 driver->dependent_files->string[i],
1943 if (!W_ERROR_IS_OK(*perr)) {
1944 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1955 TALLOC_FREE(smb_dname);
1958 vfs_ChDir(conn, oldcwd);
1962 if (W_ERROR_EQUAL(*perr, WERR_OK)) {
1966 return WERR_UNKNOWN_PRINTER_DRIVER;
1971 /****************************************************************************
1972 ****************************************************************************/
1973 int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8 *buf, int buflen)
1975 enum ndr_err_code ndr_err;
1980 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
1982 (ndr_push_flags_fn_t)
1983 ndr_push_spoolss_DeviceMode);
1984 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1985 DEBUG(10, ("pack_devicemode: "
1986 "error encoding spoolss_DeviceMode\n"));
1993 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
1996 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
2003 /****************************************************************************
2004 ****************************************************************************/
2005 int unpack_devicemode(TALLOC_CTX *mem_ctx,
2006 const uint8 *buf, int buflen,
2007 struct spoolss_DeviceMode **devmode)
2009 struct spoolss_DeviceMode *dm;
2010 enum ndr_err_code ndr_err;
2018 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
2023 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2028 blob = data_blob_const(data, data_len);
2030 ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
2031 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
2032 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2033 DEBUG(10, ("unpack_devicemode: "
2034 "error parsing spoolss_DeviceMode\n"));
2038 DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
2039 dm->devicename, dm->formname));
2040 if (dm->driverextra_data.data) {
2041 DEBUG(8, ("with a private section of %d bytes\n",
2042 dm->__driverextra_length));
2052 /****************************************************************************
2053 Pack all values in all printer keys
2054 ***************************************************************************/
2056 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2060 struct regval_blob *val;
2061 struct regval_ctr *val_ctr;
2068 /* loop over all keys */
2070 for ( i=0; i<data->num_keys; i++ ) {
2071 val_ctr = data->keys[i].values;
2072 num_values = regval_ctr_numvals( val_ctr );
2074 /* pack the keyname followed by a empty value */
2076 len += tdb_pack(buf+len, buflen-len, "pPdB",
2077 &data->keys[i].name,
2083 /* now loop over all values */
2085 for ( j=0; j<num_values; j++ ) {
2086 /* pathname should be stored as <key>\<value> */
2088 val = regval_ctr_specific_value( val_ctr, j );
2089 if (asprintf(&path, "%s\\%s",
2091 regval_name(val)) < 0) {
2095 len += tdb_pack(buf+len, buflen-len, "pPdB",
2100 regval_data_p(val) );
2102 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2110 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2116 /****************************************************************************
2117 ****************************************************************************/
2118 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2124 TDB_DATA kbuf, dbuf;
2127 * in addprinter: no servername and the printer is the name
2128 * in setprinter: servername is \\server
2129 * and printer is \\server\\printer
2131 * Samba manages only local printers.
2132 * we currently don't support things like i
2133 * path=\\other_server\printer
2135 * We only store the printername, not \\server\printername
2138 if ( info->servername[0] != '\0' ) {
2139 trim_string(info->printername, info->servername, NULL);
2140 trim_char(info->printername, '\\', '\0');
2141 info->servername[0]='\0';
2145 * JFM: one day I'll forget.
2146 * below that's info->portname because that's the SAMBA sharename
2147 * and I made NT 'thinks' it's the portname
2148 * the info->sharename is the thing you can name when you add a printer
2149 * that's the short-name when you create shared printer for 95/98
2150 * So I've made a limitation in SAMBA: you can only have 1 printer model
2151 * behind a SAMBA share.
2159 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2162 info->default_priority,
2179 info->printprocessor,
2183 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2184 retlen = pack_values( info->data, buf+len, buflen-len );
2191 if (buflen != len) {
2192 buf = (uint8 *)SMB_REALLOC(buf, len);
2194 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2202 kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2207 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2210 if (!W_ERROR_IS_OK(ret))
2211 DEBUG(8, ("error updating printer to tdb on disk\n"));
2215 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2216 info->sharename, info->drivername, info->portname, len));
2221 /****************************************************************************
2222 Create and allocate a default devicemode.
2223 ****************************************************************************/
2225 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
2226 const char *devicename,
2227 struct spoolss_DeviceMode **devmode)
2229 struct spoolss_DeviceMode *dm;
2232 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2237 dname = talloc_asprintf(dm, "%s", devicename);
2238 if (dname == NULL) {
2241 if (strlen(dname) > MAXDEVICENAME) {
2242 dname[MAXDEVICENAME] = '\0';
2244 dm->devicename = dname;
2246 dm->formname = talloc_strdup(dm, "Letter");
2247 if (dm->formname == NULL) {
2251 dm->specversion = DMSPEC_NT4_AND_ABOVE;
2252 dm->driverversion = 0x0400;
2254 dm->__driverextra_length = 0;
2255 dm->fields = DEVMODE_FORMNAME |
2257 DEVMODE_PRINTQUALITY |
2258 DEVMODE_DEFAULTSOURCE |
2262 DEVMODE_ORIENTATION;
2263 dm->orientation = DMORIENT_PORTRAIT;
2264 dm->papersize = DMPAPER_LETTER;
2265 dm->paperlength = 0;
2269 dm->defaultsource = DMBIN_FORMSOURCE;
2270 dm->printquality = DMRES_HIGH; /* 0x0258 */
2271 dm->color = DMRES_MONOCHROME;
2272 dm->duplex = DMDUP_SIMPLEX;
2273 dm->yresolution = 0;
2274 dm->ttoption = DMTT_SUBDEV;
2275 dm->collate = DMCOLLATE_FALSE;
2285 dm->displayflags = 0;
2286 dm->displayfrequency = 0;
2289 dm->panningwidth = 0;
2290 dm->panningheight = 0;
2292 dm->driverextra_data.data = NULL;
2293 dm->driverextra_data.length = 0;
2299 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
2300 struct spoolss_security_descriptor **secdesc)
2302 struct security_ace ace[7]; /* max number of ace entries */
2305 struct security_acl *psa = NULL;
2306 struct security_descriptor *psd = NULL;
2307 struct dom_sid adm_sid;
2310 /* Create an ACE where Everyone is allowed to print */
2312 sa = PRINTER_ACE_PRINT;
2313 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2314 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2316 /* Add the domain admins group if we are a DC */
2319 struct dom_sid domadmins_sid;
2321 sid_compose(&domadmins_sid, get_global_sam_sid(),
2324 sa = PRINTER_ACE_FULL_CONTROL;
2325 init_sec_ace(&ace[i++], &domadmins_sid,
2326 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2327 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2328 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2329 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2331 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
2332 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
2334 sa = PRINTER_ACE_FULL_CONTROL;
2335 init_sec_ace(&ace[i++], &adm_sid,
2336 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2337 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2338 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2339 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2342 /* add BUILTIN\Administrators as FULL CONTROL */
2344 sa = PRINTER_ACE_FULL_CONTROL;
2345 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2346 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2347 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2348 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2349 SEC_ACE_TYPE_ACCESS_ALLOWED,
2350 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2352 /* add BUILTIN\Print Operators as FULL CONTROL */
2354 sa = PRINTER_ACE_FULL_CONTROL;
2355 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2356 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2357 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2358 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2359 SEC_ACE_TYPE_ACCESS_ALLOWED,
2360 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2362 /* Make the security descriptor owned by the BUILTIN\Administrators */
2364 /* The ACL revision number in rpc_secdesc.h differs from the one
2365 created by NT when setting ACE entries in printer
2366 descriptors. NT4 complains about the property being edited by a
2369 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
2370 psd = make_sec_desc(mem_ctx,
2372 SEC_DESC_SELF_RELATIVE,
2373 &global_sid_Builtin_Administrators,
2374 &global_sid_Builtin_Administrators,
2381 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2385 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2386 (unsigned int)sd_size));
2393 /****************************************************************************
2394 Allocate and initialize a new slot.
2395 ***************************************************************************/
2397 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2403 if ( !name || !data )
2406 /* allocate another slot in the NT_PRINTER_KEY array */
2408 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2409 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2415 key_index = data->num_keys;
2417 /* initialze new key */
2419 data->keys[key_index].name = talloc_strdup( data, name );
2421 werr = regval_ctr_init(data, &(data->keys[key_index].values));
2422 if (!W_ERROR_IS_OK(werr)) {
2428 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2433 /****************************************************************************
2434 search for a registry key name in the existing printer data
2435 ***************************************************************************/
2437 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2441 for ( i=0; i<data->num_keys; i++ ) {
2442 if ( strequal( data->keys[i].name, name ) ) {
2444 /* cleanup memory */
2446 TALLOC_FREE( data->keys[i].name );
2447 TALLOC_FREE( data->keys[i].values );
2449 /* if not the end of the array, move remaining elements down one slot */
2452 if ( data->num_keys && (i < data->num_keys) )
2453 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2460 return data->num_keys;
2463 /****************************************************************************
2464 search for a registry key name in the existing printer data
2465 ***************************************************************************/
2467 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2472 if ( !data || !name )
2475 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2477 /* loop over all existing keys */
2479 for ( i=0; i<data->num_keys; i++ ) {
2480 if ( strequal(data->keys[i].name, name) ) {
2481 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2491 /****************************************************************************
2492 ***************************************************************************/
2494 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2498 int num_subkeys = 0;
2500 fstring *subkeys_ptr = NULL;
2511 /* special case of asking for the top level printer data registry key names */
2513 if ( strlen(key) == 0 ) {
2514 for ( i=0; i<data->num_keys; i++ ) {
2516 /* found a match, so allocate space and copy the name */
2518 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2519 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2524 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2531 /* asking for the subkeys of some key */
2532 /* subkey paths are stored in the key name using '\' as the delimiter */
2534 for ( i=0; i<data->num_keys; i++ ) {
2535 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2537 /* if we found the exact key, then break */
2538 key_len = strlen( key );
2539 if ( strlen(data->keys[i].name) == key_len )
2542 /* get subkey path */
2544 p = data->keys[i].name + key_len;
2547 fstrcpy( subkeyname, p );
2548 if ( (p = strchr( subkeyname, '\\' )) )
2551 /* don't add a key more than once */
2553 for ( j=0; j<num_subkeys; j++ ) {
2554 if ( strequal( subkeys_ptr[j], subkeyname ) )
2558 if ( j != num_subkeys )
2561 /* found a match, so allocate space and copy the name */
2563 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2564 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2569 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2575 /* return error if the key was not found */
2577 if ( i == data->num_keys ) {
2578 SAFE_FREE(subkeys_ptr);
2583 /* tag off the end */
2586 fstrcpy(subkeys_ptr[num_subkeys], "" );
2588 *subkeys = subkeys_ptr;
2594 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
2597 regval_ctr_delvalue(ctr, val_name);
2598 regval_ctr_addvalue_sz(ctr, val_name, sz);
2601 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
2604 regval_ctr_delvalue(ctr, val_name);
2605 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2606 (uint8 *) &dword, sizeof(dword));
2609 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
2612 uint8 bin_bool = (b ? 1 : 0);
2613 regval_ctr_delvalue(ctr, val_name);
2614 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2615 (uint8 *) &bin_bool, sizeof(bin_bool));
2618 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
2619 const char *multi_sz)
2626 regval_ctr_delvalue(ctr, val_name);
2627 regval_ctr_addvalue_multi_sz(ctr, val_name, a);
2630 /****************************************************************************
2631 * Map spoolss_PrinterInfo2 data into DsSpooler keys for publishing.
2633 * @param mem_ctx allocation context
2634 * @param info2 spoolss_PrinterInfo2 describing printer
2635 * @param pdata the talloced printer data
2636 * @return bool indicating success or failure
2637 ***************************************************************************/
2639 static bool map_nt_printer_info2_to_dsspooler(TALLOC_CTX *mem_ctx,
2640 struct spoolss_PrinterInfo2 *info2,
2641 NT_PRINTER_DATA **pdata)
2643 NT_PRINTER_DATA *data;
2644 struct regval_ctr *ctr = NULL;
2646 const char *dnssuffix;
2647 char *allocated_string = NULL;
2648 const char *ascii_str;
2651 data = talloc_zero(mem_ctx, NT_PRINTER_DATA);
2652 if (!data) return false;
2655 i = add_new_printer_key(data, SPOOL_DSSPOOLER_KEY);
2656 ctr = data->keys[i].values;
2658 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2659 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2661 /* we make the assumption that the netbios name is the same
2662 as the DNS name sinc ethe former will be what we used to
2665 dnssuffix = get_mydnsdomname(talloc_tos());
2666 if (dnssuffix && *dnssuffix) {
2667 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2669 fstrcpy( longname, global_myname() );
2672 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2674 if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
2678 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2679 SAFE_FREE(allocated_string);
2681 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2682 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2683 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2684 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2685 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2686 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2687 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2688 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2689 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2691 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2692 (info2->attributes &
2693 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2695 switch (info2->attributes & 0x3) {
2697 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2700 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2703 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2706 ascii_str = "unknown";
2708 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2714 /*****************************************************************
2715 ****************************************************************/
2717 static void store_printer_guid(const char *printer, struct GUID guid)
2719 TALLOC_CTX *tmp_ctx;
2720 struct auth_serversupplied_info *server_info = NULL;
2721 const char *guid_str;
2726 tmp_ctx = talloc_new(NULL);
2728 DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
2732 status = make_server_info_system(tmp_ctx, &server_info);
2733 if (!NT_STATUS_IS_OK(status)) {
2734 DEBUG(0, ("store_printer_guid: "
2735 "Could not create system server_info\n"));
2739 guid_str = GUID_string(tmp_ctx, &guid);
2741 DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
2745 /* We used to store this as a REG_BINARY but that causes
2748 if (!push_reg_sz(tmp_ctx, &blob, guid_str)) {
2749 DEBUG(0, ("store_printer_guid: "
2750 "Could not marshall string %s for objectGUID\n",
2755 result = winreg_set_printer_dataex(tmp_ctx, server_info, printer,
2756 SPOOL_DSSPOOLER_KEY, "objectGUID",
2757 REG_SZ, blob.data, blob.length);
2758 if (!W_ERROR_IS_OK(result)) {
2759 DEBUG(0, ("store_printer_guid: "
2760 "Failed to store GUID for printer %s\n", printer));
2764 talloc_free(tmp_ctx);
2767 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2768 struct spoolss_PrinterInfo2 *pinfo2)
2772 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
2773 char *srv_dn_utf8, **srv_cn_utf8;
2776 const char *attrs[] = {"objectGUID", NULL};
2778 WERROR win_rc = WERR_OK;
2779 size_t converted_size;
2780 NT_PRINTER_DATA *pdata;
2781 const char *printer = pinfo2->sharename;
2783 /* build the ads mods */
2784 ctx = talloc_init("nt_printer_publish_ads");
2789 DEBUG(5, ("publishing printer %s\n", printer));
2791 if (!map_nt_printer_info2_to_dsspooler(ctx, pinfo2, &pdata)) {
2793 return WERR_SERVER_UNAVAILABLE;
2796 /* figure out where to publish */
2797 ads_find_machine_acct(ads, &res, global_myname());
2799 /* We use ldap_get_dn here as we need the answer
2800 * in utf8 to call ldap_explode_dn(). JRA. */
2802 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
2805 return WERR_SERVER_UNAVAILABLE;
2807 ads_msgfree(ads, res);
2808 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2811 ldap_memfree(srv_dn_utf8);
2812 return WERR_SERVER_UNAVAILABLE;
2814 /* Now convert to CH_UNIX. */
2815 if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
2817 ldap_memfree(srv_dn_utf8);
2818 ldap_memfree(srv_cn_utf8);
2819 return WERR_SERVER_UNAVAILABLE;
2821 if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
2823 ldap_memfree(srv_dn_utf8);
2824 ldap_memfree(srv_cn_utf8);
2825 TALLOC_FREE(srv_dn);
2826 return WERR_SERVER_UNAVAILABLE;
2829 ldap_memfree(srv_dn_utf8);
2830 ldap_memfree(srv_cn_utf8);
2832 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
2833 if (!srv_cn_escaped) {
2835 return WERR_SERVER_UNAVAILABLE;
2837 sharename_escaped = escape_rdn_val_string_alloc(printer);
2838 if (!sharename_escaped) {
2839 SAFE_FREE(srv_cn_escaped);
2841 return WERR_SERVER_UNAVAILABLE;
2844 prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
2846 SAFE_FREE(srv_cn_escaped);
2847 SAFE_FREE(sharename_escaped);
2849 mods = ads_init_mods(ctx);
2857 get_local_printer_publishing_data(ctx, &mods, pdata);
2858 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, printer);
2861 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
2862 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
2864 for (i=0; mods[i] != 0; i++)
2866 mods[i] = (LDAPMod *)-1;
2867 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2870 if (!ADS_ERR_OK(ads_rc)) {
2871 DEBUG(3, ("error publishing %s: %s\n",
2872 printer, ads_errstr(ads_rc)));
2875 /* retreive the guid and store it locally */
2876 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2878 ads_pull_guid(ads, res, &guid);
2879 ads_msgfree(ads, res);
2880 store_printer_guid(printer, guid);
2887 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
2888 const char *printer)
2891 LDAPMessage *res = NULL;
2892 char *prt_dn = NULL;
2894 DEBUG(5, ("unpublishing printer %s\n", printer));
2896 /* remove the printer from the directory */
2897 ads_rc = ads_find_printer_on_server(ads, &res,
2898 printer, global_myname());
2900 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
2901 prt_dn = ads_get_dn(ads, talloc_tos(), res);
2903 ads_msgfree(ads, res);
2906 ads_rc = ads_del_dn(ads, prt_dn);
2907 TALLOC_FREE(prt_dn);
2911 ads_msgfree(ads, res);
2916 /****************************************************************************
2917 * Publish a printer in the directory
2919 * @param mem_ctx memory context
2920 * @param server_info server_info to access winreg pipe
2921 * @param pinfo2 printer information
2922 * @param action publish/unpublish action
2923 * @return WERROR indicating status of publishing
2924 ***************************************************************************/
2926 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
2927 struct auth_serversupplied_info *server_info,
2928 struct spoolss_PrinterInfo2 *pinfo2,
2931 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ATTRIBUTES;
2932 struct spoolss_SetPrinterInfo2 *sinfo2;
2934 ADS_STRUCT *ads = NULL;
2937 sinfo2 = talloc_zero(mem_ctx, struct spoolss_SetPrinterInfo2);
2943 case DSPRINT_PUBLISH:
2944 case DSPRINT_UPDATE:
2945 pinfo2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2947 case DSPRINT_UNPUBLISH:
2948 pinfo2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2951 win_rc = WERR_NOT_SUPPORTED;
2955 sinfo2->attributes = pinfo2->attributes;
2957 win_rc = winreg_update_printer(mem_ctx, server_info,
2958 pinfo2->sharename, info2_mask,
2959 sinfo2, NULL, NULL);
2960 if (!W_ERROR_IS_OK(win_rc)) {
2961 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
2965 TALLOC_FREE(sinfo2);
2967 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
2969 DEBUG(3, ("ads_init() failed\n"));
2970 win_rc = WERR_SERVER_UNAVAILABLE;
2973 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2974 SAFE_FREE(ads->auth.password);
2975 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2978 /* ads_connect() will find the DC for us */
2979 ads_rc = ads_connect(ads);
2980 if (!ADS_ERR_OK(ads_rc)) {
2981 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2982 win_rc = WERR_ACCESS_DENIED;
2987 case DSPRINT_PUBLISH:
2988 case DSPRINT_UPDATE:
2989 win_rc = nt_printer_publish_ads(ads, pinfo2);
2991 case DSPRINT_UNPUBLISH:
2992 win_rc = nt_printer_unpublish_ads(ads, pinfo2->sharename);
3001 WERROR check_published_printers(void)
3004 ADS_STRUCT *ads = NULL;
3006 int n_services = lp_numservices();
3007 TALLOC_CTX *tmp_ctx = NULL;
3008 struct auth_serversupplied_info *server_info = NULL;
3009 struct spoolss_PrinterInfo2 *pinfo2;
3013 tmp_ctx = talloc_new(NULL);
3014 if (!tmp_ctx) return WERR_NOMEM;
3016 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3018 DEBUG(3, ("ads_init() failed\n"));
3019 return WERR_SERVER_UNAVAILABLE;
3021 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3022 SAFE_FREE(ads->auth.password);
3023 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3026 /* ads_connect() will find the DC for us */
3027 ads_rc = ads_connect(ads);
3028 if (!ADS_ERR_OK(ads_rc)) {
3029 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3030 result = WERR_ACCESS_DENIED;
3034 status = make_server_info_system(tmp_ctx, &server_info);
3035 if (!NT_STATUS_IS_OK(status)) {
3036 DEBUG(0, ("check_published_printers: "
3037 "Could not create system server_info\n"));
3038 result = WERR_ACCESS_DENIED;
3042 for (snum = 0; snum < n_services; snum++) {
3043 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
3047 result = winreg_get_printer(tmp_ctx, server_info, NULL,
3048 lp_servicename(snum), &pinfo2);
3049 if (!W_ERROR_IS_OK(result)) {
3053 if (pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
3054 nt_printer_publish_ads(ads, pinfo2);
3057 TALLOC_FREE(pinfo2);
3063 ads_kdestroy("MEMORY:prtpub_cache");
3064 talloc_free(tmp_ctx);
3068 bool is_printer_published(TALLOC_CTX *mem_ctx,
3069 struct auth_serversupplied_info *server_info,
3070 char *servername, char *printer, struct GUID *guid,
3071 struct spoolss_PrinterInfo2 **info2)
3073 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3074 enum winreg_Type type;
3080 result = winreg_get_printer(mem_ctx, server_info,
3081 servername, printer, &pinfo2);
3082 if (!W_ERROR_IS_OK(result)) {
3086 if (!(pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) {
3087 TALLOC_FREE(pinfo2);
3095 /* fetching printer guids really ought to be a separate function. */
3097 result = winreg_get_printer_dataex(mem_ctx, server_info, printer,
3098 SPOOL_DSSPOOLER_KEY, "objectGUID",
3099 &type, &data, &data_size);
3100 if (!W_ERROR_IS_OK(result)) {
3101 TALLOC_FREE(pinfo2);
3105 /* We used to store the guid as REG_BINARY, then swapped
3106 to REG_SZ for Vista compatibility so check for both */
3110 status = GUID_from_string((char *)data, guid);
3111 if (!NT_STATUS_IS_OK(status)) {
3112 TALLOC_FREE(pinfo2);
3118 if (data_size != sizeof(struct GUID)) {
3119 TALLOC_FREE(pinfo2);
3122 memcpy(guid, data, sizeof(struct GUID));
3125 DEBUG(0,("is_printer_published: GUID value stored as "
3126 "invaluid type (%d)\n", type));
3132 *info2 = talloc_move(mem_ctx, &pinfo2);
3134 talloc_free(pinfo2);
3138 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
3139 struct auth_serversupplied_info *server_info,
3140 struct spoolss_PrinterInfo2 *pinfo2,
3146 WERROR check_published_printers(void)
3151 bool is_printer_published(TALLOC_CTX *mem_ctx,
3152 struct auth_serversupplied_info *server_info,
3153 char *servername, char *printer, struct GUID *guid,
3154 struct spoolss_PrinterInfo2 **info2)
3158 #endif /* HAVE_ADS */
3160 /****************************************************************************
3161 ***************************************************************************/
3163 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3165 NT_PRINTER_DATA *data;
3167 int removed_keys = 0;
3171 empty_slot = data->num_keys;
3174 return WERR_INVALID_PARAM;
3176 /* remove all keys */
3178 if ( !strlen(key) ) {
3180 TALLOC_FREE( data );
3184 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3190 /* remove a specific key (and all subkeys) */
3192 for ( i=0; i<data->num_keys; i++ ) {
3193 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3194 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3195 data->keys[i].name));
3197 TALLOC_FREE( data->keys[i].name );
3198 TALLOC_FREE( data->keys[i].values );
3200 /* mark the slot as empty */
3202 ZERO_STRUCTP( &data->keys[i] );
3206 /* find the first empty slot */
3208 for ( i=0; i<data->num_keys; i++ ) {
3209 if ( !data->keys[i].name ) {
3216 if ( i == data->num_keys )
3217 /* nothing was removed */
3218 return WERR_INVALID_PARAM;
3220 /* move everything down */
3222 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3223 if ( data->keys[i].name ) {
3224 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3225 ZERO_STRUCTP( &data->keys[i] );
3233 data->num_keys -= removed_keys;
3235 /* sanity check to see if anything is left */
3237 if ( !data->num_keys ) {
3238 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3240 SAFE_FREE( data->keys );
3241 ZERO_STRUCTP( data );
3247 /****************************************************************************
3248 ***************************************************************************/
3250 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3252 WERROR result = WERR_OK;
3255 /* we must have names on non-zero length */
3257 if ( !key || !*key|| !value || !*value )
3258 return WERR_INVALID_NAME;
3260 /* find the printer key first */
3262 key_index = lookup_printerkey( p2->data, key );
3263 if ( key_index == -1 )
3266 /* make sure the value exists so we can return the correct error code */
3268 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3269 return WERR_BADFILE;
3271 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3273 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3279 /****************************************************************************
3280 ***************************************************************************/
3282 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3283 uint32 type, uint8 *data, int real_len )
3285 WERROR result = WERR_OK;
3288 /* we must have names on non-zero length */
3290 if ( !key || !*key|| !value || !*value )
3291 return WERR_INVALID_NAME;
3293 /* find the printer key first */
3295 key_index = lookup_printerkey( p2->data, key );
3296 if ( key_index == -1 )
3297 key_index = add_new_printer_key( p2->data, key );
3299 if ( key_index == -1 )
3302 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3303 type, data, real_len );
3305 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3306 key, value, type, real_len ));
3311 /****************************************************************************
3312 ***************************************************************************/
3314 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3318 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3321 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3324 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3327 /****************************************************************************
3328 ***************************************************************************/
3330 static char *win_driver;
3331 static char *os2_driver;
3333 static const char *get_win_driver(void)
3335 if (win_driver == NULL) {
3341 static const char *get_os2_driver(void)
3343 if (os2_driver == NULL) {
3349 static bool set_driver_mapping(const char *from, const char *to)
3351 SAFE_FREE(win_driver);
3352 SAFE_FREE(os2_driver);
3354 win_driver = SMB_STRDUP(from);
3355 os2_driver = SMB_STRDUP(to);
3357 if (win_driver == NULL || os2_driver == NULL) {
3358 SAFE_FREE(win_driver);
3359 SAFE_FREE(os2_driver);
3368 * @brief Map a Windows driver to a OS/2 driver.
3370 * @param[in] mem_ctx The memory context to use.
3372 * @param[in,out] pdrivername The drivername of Windows to remap.
3374 * @return WERR_OK on success, a corresponding WERROR on failure.
3376 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
3378 const char *mapfile = lp_os2_driver_map();
3379 char **lines = NULL;
3380 const char *drivername;
3384 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
3385 return WERR_INVALID_PARAMETER;
3388 drivername = *pdrivername;
3390 if (mapfile[0] == '\0') {
3391 return WERR_BADFILE;
3394 if (strequal(drivername, get_win_driver())) {
3395 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3396 drivername, get_os2_driver()));
3397 drivername = talloc_strdup(mem_ctx, get_os2_driver());
3398 if (drivername == NULL) {
3401 *pdrivername = drivername;
3405 lines = file_lines_load(mapfile, &numlines, 0, NULL);
3406 if (numlines == 0 || lines == NULL) {
3407 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
3412 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3414 for( i = 0; i < numlines; i++) {
3415 char *nt_name = lines[i];
3416 char *os2_name = strchr(nt_name, '=');
3418 if (os2_name == NULL) {
3424 while (isspace(*nt_name)) {
3428 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
3433 int l = strlen(nt_name);
3434 while (l && isspace(nt_name[l - 1])) {
3440 while (isspace(*os2_name)) {
3445 int l = strlen(os2_name);
3446 while (l && isspace(os2_name[l-1])) {
3452 if (strequal(nt_name, drivername)) {
3453 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
3454 set_driver_mapping(drivername, os2_name);
3455 drivername = talloc_strdup(mem_ctx, os2_name);
3457 if (drivername == NULL) {
3460 *pdrivername = drivername;
3469 /****************************************************************************
3470 Debugging function, dump at level 6 the struct in the logs.
3471 ****************************************************************************/
3472 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3475 NT_PRINTER_INFO_LEVEL_2 *info2;
3477 DEBUG(106,("Dumping printer at level [%d]\n", level));
3482 if (printer->info_2 == NULL)
3486 info2=printer->info_2;
3488 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3489 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3490 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3491 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3492 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3493 DEBUGADD(106,("status:[%d]\n", info2->status));
3494 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3495 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3496 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3497 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3498 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3500 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3501 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3502 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3503 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3504 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3505 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3506 DEBUGADD(106,("location:[%s]\n", info2->location));
3507 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3508 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3509 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3510 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3516 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3524 /****************************************************************************
3525 Update the changeid time.
3526 This is SO NASTY as some drivers need this to change, others need it
3527 static. This value will change every second, and I must hope that this
3528 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3530 ****************************************************************************/
3532 static uint32 rev_changeid(void)
3536 get_process_uptime(&tv);
3539 /* Return changeid as msec since spooler restart */
3540 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3543 * This setting seems to work well but is too untested
3544 * to replace the above calculation. Left in for experiementation
3545 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3547 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3553 * The function below are the high level ones.
3554 * only those ones must be called from the spoolss code.
3558 /****************************************************************************
3559 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3560 ****************************************************************************/
3562 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3566 dump_a_printer(printer, level);
3572 * Update the changestamp. Emperical tests show that the
3573 * ChangeID is always updated,but c_setprinter is
3574 * global spooler variable (not per printer).
3577 /* ChangeID **must** be increasing over the lifetime
3578 of client's spoolss service in order for the
3579 client's cache to show updates */
3581 printer->info_2->changeid = rev_changeid();
3584 * Because one day someone will ask:
3585 * NT->NT An admin connection to a remote
3586 * printer show changes imeediately in
3587 * the properities dialog
3589 * A non-admin connection will only show the
3590 * changes after viewing the properites page
3591 * 2 times. Seems to be related to a
3592 * race condition in the client between the spooler
3593 * updating the local cache and the Explorer.exe GUI
3594 * actually displaying the properties.
3596 * This is fixed in Win2k. admin/non-admin
3597 * connections both display changes immediately.
3602 result=update_a_printer_2(printer->info_2);
3606 result=WERR_UNKNOWN_LEVEL;
3613 /****************************************************************************
3614 Deletes a NT_PRINTER_INFO_LEVEL struct.
3615 ****************************************************************************/
3617 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3619 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3626 TALLOC_FREE(printer->info_2);
3630 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
3634 TALLOC_FREE(*pp_printer);
3639 /****************************************************************************
3640 ****************************************************************************/
3642 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
3643 struct spoolss_DriverInfo8 *_info8)
3645 struct spoolss_DriverInfo8 info8;
3651 info8.version = r->info.info3->version;
3652 info8.driver_name = r->info.info3->driver_name;
3653 info8.architecture = r->info.info3->architecture;
3654 info8.driver_path = r->info.info3->driver_path;
3655 info8.data_file = r->info.info3->data_file;
3656 info8.config_file = r->info.info3->config_file;
3657 info8.help_file = r->info.info3->help_file;
3658 info8.monitor_name = r->info.info3->monitor_name;
3659 info8.default_datatype = r->info.info3->default_datatype;
3660 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
3661 info8.dependent_files = r->info.info3->dependent_files->string;
3665 info8.version = r->info.info6->version;
3666 info8.driver_name = r->info.info6->driver_name;
3667 info8.architecture = r->info.info6->architecture;
3668 info8.driver_path = r->info.info6->driver_path;
3669 info8.data_file = r->info.info6->data_file;
3670 info8.config_file = r->info.info6->config_file;
3671 info8.help_file = r->info.info6->help_file;
3672 info8.monitor_name = r->info.info6->monitor_name;
3673 info8.default_datatype = r->info.info6->default_datatype;
3674 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
3675 info8.dependent_files = r->info.info6->dependent_files->string;
3677 info8.driver_date = r->info.info6->driver_date;
3678 info8.driver_version = r->info.info6->driver_version;
3679 info8.manufacturer_name = r->info.info6->manufacturer_name;
3680 info8.manufacturer_url = r->info.info6->manufacturer_url;
3681 info8.hardware_id = r->info.info6->hardware_id;
3682 info8.provider = r->info.info6->provider;
3685 info8.version = r->info.info8->version;
3686 info8.driver_name = r->info.info8->driver_name;
3687 info8.architecture = r->info.info8->architecture;
3688 info8.driver_path = r->info.info8->driver_path;
3689 info8.data_file = r->info.info8->data_file;
3690 info8.config_file = r->info.info8->config_file;
3691 info8.help_file = r->info.info8->help_file;
3692 info8.monitor_name = r->info.info8->monitor_name;
3693 info8.default_datatype = r->info.info8->default_datatype;
3694 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
3695 info8.dependent_files = r->info.info8->dependent_files->string;
3697 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
3698 info8.previous_names = r->info.info8->previous_names->string;
3700 info8.driver_date = r->info.info8->driver_date;
3701 info8.driver_version = r->info.info8->driver_version;
3702 info8.manufacturer_name = r->info.info8->manufacturer_name;
3703 info8.manufacturer_url = r->info.info8->manufacturer_url;
3704 info8.hardware_id = r->info.info8->hardware_id;
3705 info8.provider = r->info.info8->provider;
3706 info8.print_processor = r->info.info8->print_processor;
3707 info8.vendor_setup = r->info.info8->vendor_setup;
3708 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
3709 info8.color_profiles = r->info.info8->color_profiles->string;
3711 info8.inf_path = r->info.info8->inf_path;
3712 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
3713 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
3714 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
3716 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
3717 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
3729 /****************************************************************************
3730 Determine whether or not a particular driver is currently assigned
3732 ****************************************************************************/
3734 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
3735 struct auth_serversupplied_info *server_info,
3736 const struct spoolss_DriverInfo8 *r)
3739 int n_services = lp_numservices();
3740 bool in_use = False;
3741 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3748 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
3750 /* loop through the printers.tdb and check for the drivername */
3752 for (snum=0; snum<n_services && !in_use; snum++) {
3753 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
3757 result = winreg_get_printer(mem_ctx, server_info, NULL,
3758 lp_servicename(snum), &pinfo2);
3759 if (!W_ERROR_IS_OK(result)) {
3760 continue; /* skip */
3763 if (strequal(r->driver_name, pinfo2->drivername)) {
3767 TALLOC_FREE(pinfo2);
3770 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
3773 struct spoolss_DriverInfo8 *driver;
3776 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
3778 /* we can still remove the driver if there is one of
3779 "Windows NT x86" version 2 or 3 left */
3781 if (!strequal("Windows NT x86", r->architecture)) {
3782 werr = winreg_get_driver(mem_ctx, server_info,
3787 } else if (r->version == 2) {
3788 werr = winreg_get_driver(mem_ctx, server_info,
3792 } else if (r->version == 3) {
3793 werr = winreg_get_driver(mem_ctx, server_info,
3798 DEBUG(0, ("printer_driver_in_use: ERROR!"
3799 " unknown driver version (%d)\n",
3801 werr = WERR_UNKNOWN_PRINTER_DRIVER;
3804 /* now check the error code */
3806 if ( W_ERROR_IS_OK(werr) ) {
3807 /* it's ok to remove the driver, we have other architctures left */
3809 talloc_free(driver);
3813 /* report that the driver is not in use by default */
3819 /**********************************************************************
3820 Check to see if a ogiven file is in use by *info
3821 *********************************************************************/
3823 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
3830 /* mz: skip files that are in the list but already deleted */
3831 if (!file || !file[0]) {
3835 if (strequal(file, info->driver_path))
3838 if (strequal(file, info->data_file))
3841 if (strequal(file, info->config_file))
3844 if (strequal(file, info->help_file))
3847 /* see of there are any dependent files to examine */
3849 if (!info->dependent_files)
3852 while (info->dependent_files[i] && *info->dependent_files[i]) {
3853 if (strequal(file, info->dependent_files[i]))
3862 /**********************************************************************
3863 Utility function to remove the dependent file pointed to by the
3864 input parameter from the list
3865 *********************************************************************/
3867 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
3870 /* bump everything down a slot */
3872 while (files && files[idx+1]) {
3873 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
3882 /**********************************************************************
3883 Check if any of the files used by src are also used by drv
3884 *********************************************************************/
3886 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
3887 struct spoolss_DriverInfo8 *src,
3888 const struct spoolss_DriverInfo8 *drv)
3890 bool in_use = False;
3896 /* check each file. Remove it from the src structure if it overlaps */
3898 if (drv_file_in_use(src->driver_path, drv)) {
3900 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
3901 src->driver_path = talloc_strdup(mem_ctx, "");
3902 if (!src->driver_path) { return false; }
3905 if (drv_file_in_use(src->data_file, drv)) {
3907 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
3908 src->data_file = talloc_strdup(mem_ctx, "");
3909 if (!src->data_file) { return false; }
3912 if (drv_file_in_use(src->config_file, drv)) {
3914 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
3915 src->config_file = talloc_strdup(mem_ctx, "");
3916 if (!src->config_file) { return false; }
3919 if (drv_file_in_use(src->help_file, drv)) {
3921 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
3922 src->help_file = talloc_strdup(mem_ctx, "");
3923 if (!src->help_file) { return false; }
3926 /* are there any dependentfiles to examine? */
3928 if (!src->dependent_files)
3931 while (src->dependent_files[i] && *src->dependent_files[i]) {
3932 if (drv_file_in_use(src->dependent_files[i], drv)) {
3934 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
3935 trim_dependent_file(mem_ctx, src->dependent_files, i);
3943 /****************************************************************************
3944 Determine whether or not a particular driver files are currently being
3945 used by any other driver.
3947 Return value is True if any files were in use by other drivers
3948 and False otherwise.
3950 Upon return, *info has been modified to only contain the driver files
3951 which are not in use
3955 This needs to check all drivers to ensure that all files in use
3956 have been removed from *info, not just the ones in the first
3958 ****************************************************************************/
3960 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
3961 struct auth_serversupplied_info *server_info,
3962 struct spoolss_DriverInfo8 *info)
3966 struct spoolss_DriverInfo8 *driver;
3967 bool in_use = false;
3968 uint32_t num_drivers;
3969 const char **drivers;
3975 version = info->version;
3977 /* loop over all driver versions */
3979 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
3981 /* get the list of drivers */
3983 result = winreg_get_driver_list(mem_ctx, server_info,
3984 info->architecture, version,
3985 &num_drivers, &drivers);
3986 if (!W_ERROR_IS_OK(result)) {
3990 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
3991 num_drivers, info->architecture, version));
3993 /* check each driver for overlap in files */
3995 for (i = 0; i < num_drivers; i++) {
3996 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
4000 result = winreg_get_driver(mem_ctx, server_info,
4001 info->architecture, drivers[i],
4003 if (!W_ERROR_IS_OK(result)) {
4004 talloc_free(drivers);
4008 /* check if d2 uses any files from d1 */
4009 /* only if this is a different driver than the one being deleted */
4011 if (!strequal(info->driver_name, driver->driver_name)) {
4012 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
4013 /* mz: Do not instantly return -
4014 * we need to ensure this file isn't
4015 * also in use by other drivers. */
4020 talloc_free(driver);
4023 talloc_free(drivers);
4025 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
4030 static NTSTATUS driver_unlink_internals(connection_struct *conn,
4033 struct smb_filename *smb_fname = NULL;
4036 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
4038 if (!NT_STATUS_IS_OK(status)) {
4042 status = unlink_internals(conn, NULL, 0, smb_fname, false);
4044 TALLOC_FREE(smb_fname);
4048 /****************************************************************************
4049 Actually delete the driver files. Make sure that
4050 printer_driver_files_in_use() return False before calling
4052 ****************************************************************************/
4054 bool delete_driver_files(struct auth_serversupplied_info *server_info,
4055 const struct spoolss_DriverInfo8 *r)
4060 connection_struct *conn;
4063 fstring printdollar;
4064 int printdollar_snum;
4071 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
4072 r->driver_name, r->version));
4074 fstrcpy(printdollar, "print$");
4076 printdollar_snum = find_service(printdollar);
4077 if (printdollar_snum == -1) {
4081 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
4082 lp_pathname(printdollar_snum),
4083 server_info, &oldcwd);
4084 if (!NT_STATUS_IS_OK(nt_status)) {
4085 DEBUG(0,("delete_driver_files: create_conn_struct "
4086 "returned %s\n", nt_errstr(nt_status)));
4090 if ( !CAN_WRITE(conn) ) {
4091 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4095 /* now delete the files; must strip the '\print$' string from
4098 if (r->driver_path && r->driver_path[0]) {
4099 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
4101 DEBUG(10,("deleting driverfile [%s]\n", s));
4102 driver_unlink_internals(conn, file);
4106 if (r->config_file && r->config_file[0]) {
4107 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
4109 DEBUG(10,("deleting configfile [%s]\n", s));
4110 driver_unlink_internals(conn, file);
4114 if (r->data_file && r->data_file[0]) {
4115 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
4117 DEBUG(10,("deleting datafile [%s]\n", s));
4118 driver_unlink_internals(conn, file);
4122 if (r->help_file && r->help_file[0]) {
4123 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
4125 DEBUG(10,("deleting helpfile [%s]\n", s));
4126 driver_unlink_internals(conn, file);
4130 /* check if we are done removing files */
4132 if (r->dependent_files) {
4133 while (r->dependent_files[i] && r->dependent_files[i][0]) {
4136 /* bypass the "\print$" portion of the path */
4138 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
4140 DEBUG(10,("deleting dependent file [%s]\n", file));
4141 driver_unlink_internals(conn, file);
4153 vfs_ChDir(conn, oldcwd);
4159 /****************************************************************************
4160 Store a security desc for a printer.
4161 ****************************************************************************/
4163 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
4165 struct sec_desc_buf *new_secdesc_ctr = NULL;
4166 struct sec_desc_buf *old_secdesc_ctr = NULL;
4167 TALLOC_CTX *mem_ctx = NULL;
4174 mem_ctx = talloc_init("nt_printing_setsec");
4175 if (mem_ctx == NULL)
4178 /* The old owner and group sids of the security descriptor are not
4179 present when new ACEs are added or removed by changing printer
4180 permissions through NT. If they are NULL in the new security
4181 descriptor then copy them over from the old one. */
4183 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
4184 struct dom_sid *owner_sid, *group_sid;
4185 struct security_acl *dacl, *sacl;
4186 struct security_descriptor *psd = NULL;
4189 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
4190 status = WERR_NOMEM;
4194 /* Pick out correct owner and group sids */
4196 owner_sid = secdesc_ctr->sd->owner_sid ?
4197 secdesc_ctr->sd->owner_sid :
4198 old_secdesc_ctr->sd->owner_sid;
4200 group_sid = secdesc_ctr->sd->group_sid ?
4201 secdesc_ctr->sd->group_sid :
4202 old_secdesc_ctr->sd->group_sid;
4204 dacl = secdesc_ctr->sd->dacl ?
4205 secdesc_ctr->sd->dacl :
4206 old_secdesc_ctr->sd->dacl;
4208 sacl = secdesc_ctr->sd->sacl ?
4209 secdesc_ctr->sd->sacl :
4210 old_secdesc_ctr->sd->sacl;
4212 /* Make a deep copy of the security descriptor */
4214 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
4215 owner_sid, group_sid,
4221 status = WERR_NOMEM;
4225 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4228 if (!new_secdesc_ctr) {
4229 new_secdesc_ctr = secdesc_ctr;
4232 /* Store the security descriptor in a tdb */
4234 nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
4235 &blob.data, &blob.length);
4236 if (!NT_STATUS_IS_OK(nt_status)) {
4237 status = ntstatus_to_werror(nt_status);
4241 kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
4243 dbuf.dptr = (unsigned char *)blob.data;
4244 dbuf.dsize = blob.length;
4246 if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
4249 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
4250 status = WERR_BADFUNC;
4253 /* Free malloc'ed memory */
4254 talloc_free(blob.data);
4259 talloc_destroy(mem_ctx);
4263 /****************************************************************************
4264 Construct a default security descriptor buffer for a printer.
4265 ****************************************************************************/
4267 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
4269 struct security_ace ace[7]; /* max number of ace entries */
4272 struct security_acl *psa = NULL;
4273 struct sec_desc_buf *sdb = NULL;
4274 struct security_descriptor *psd = NULL;
4275 struct dom_sid adm_sid;
4278 /* Create an ACE where Everyone is allowed to print */
4280 sa = PRINTER_ACE_PRINT;
4281 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4282 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4284 /* Add the domain admins group if we are a DC */
4287 struct dom_sid domadmins_sid;
4289 sid_compose(&domadmins_sid, get_global_sam_sid(),
4292 sa = PRINTER_ACE_FULL_CONTROL;
4293 init_sec_ace(&ace[i++], &domadmins_sid,
4294 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
4295 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
4296 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4297 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4299 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
4300 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
4302 sa = PRINTER_ACE_FULL_CONTROL;
4303 init_sec_ace(&ace[i++], &adm_sid,
4304 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
4305 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
4306 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4307 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4310 /* add BUILTIN\Administrators as FULL CONTROL */
4312 sa = PRINTER_ACE_FULL_CONTROL;
4313 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
4314 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
4315 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
4316 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
4317 SEC_ACE_TYPE_ACCESS_ALLOWED,
4318 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4320 /* add BUILTIN\Print Operators as FULL CONTROL */
4322 sa = PRINTER_ACE_FULL_CONTROL;
4323 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
4324 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
4325 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
4326 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
4327 SEC_ACE_TYPE_ACCESS_ALLOWED,
4328 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4330 /* Make the security descriptor owned by the BUILTIN\Administrators */
4332 /* The ACL revision number in rpc_secdesc.h differs from the one
4333 created by NT when setting ACE entries in printer
4334 descriptors. NT4 complains about the property being edited by a
4337 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
4338 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
4339 &global_sid_Builtin_Administrators,
4340 &global_sid_Builtin_Administrators,
4341 NULL, psa, &sd_size);
4345 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4349 sdb = make_sec_desc_buf(ctx, sd_size, psd);
4351 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4352 (unsigned int)sd_size));
4357 /****************************************************************************
4358 Get a security desc for a printer.
4359 ****************************************************************************/
4361 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
4369 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
4370 sharename = temp + 1;
4373 /* Fetch security descriptor from tdb */
4375 kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
4377 dbuf = tdb_fetch(tdb_printers, kbuf);
4380 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
4382 SAFE_FREE(dbuf.dptr);
4384 if (NT_STATUS_IS_OK(status)) {
4389 *secdesc_ctr = construct_default_printer_sdb(ctx);
4390 if (!*secdesc_ctr) {
4394 status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
4395 &blob.data, &blob.length);
4396 if (NT_STATUS_IS_OK(status)) {
4397 dbuf.dptr = (unsigned char *)blob.data;
4398 dbuf.dsize = blob.length;
4399 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
4400 talloc_free(blob.data);
4403 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4404 this security descriptor has been created when winbindd was
4405 down. Take ownership of security descriptor. */
4407 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
4408 struct dom_sid owner_sid;
4410 /* Change sd owner to workgroup administrator */
4412 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4413 struct sec_desc_buf *new_secdesc_ctr = NULL;
4414 struct security_descriptor *psd = NULL;
4419 sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
4421 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
4423 (*secdesc_ctr)->sd->group_sid,
4424 (*secdesc_ctr)->sd->sacl,
4425 (*secdesc_ctr)->sd->dacl,
4432 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4433 if (!new_secdesc_ctr) {
4437 /* Swap with other one */
4439 *secdesc_ctr = new_secdesc_ctr;
4443 nt_printing_setsec(sharename, *secdesc_ctr);
4447 if (DEBUGLEVEL >= 10) {
4448 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
4451 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4452 sharename, the_acl->num_aces));
4454 for (i = 0; i < the_acl->num_aces; i++) {
4455 DEBUG(10, ("%s %d %d 0x%08x\n",
4456 sid_string_dbg(&the_acl->aces[i].trustee),
4457 the_acl->aces[i].type, the_acl->aces[i].flags,
4458 the_acl->aces[i].access_mask));
4467 1: level not implemented
4468 2: file doesn't exist
4469 3: can't allocate memory
4470 4: can't free memory
4471 5: non existant struct
4475 A printer and a printer driver are 2 different things.
4476 NT manages them separatelly, Samba does the same.
4477 Why ? Simply because it's easier and it makes sense !
4479 Now explanation: You have 3 printers behind your samba server,
4480 2 of them are the same make and model (laser A and B). But laser B
4481 has an 3000 sheet feeder and laser A doesn't such an option.
4482 Your third printer is an old dot-matrix model for the accounting :-).
4484 If the /usr/local/samba/lib directory (default dir), you will have
4485 5 files to describe all of this.
4487 3 files for the printers (1 by printer):
4490 NTprinter_accounting
4491 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4492 NTdriver_printer model X
4493 NTdriver_printer model Y
4495 jfm: I should use this comment for the text file to explain
4496 same thing for the forms BTW.
4497 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4501 /* Convert generic access rights to printer object specific access rights.
4502 It turns out that NT4 security descriptors use generic access rights and
4503 NT5 the object specific ones. */
4505 void map_printer_permissions(struct security_descriptor *sd)
4509 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4510 se_map_generic(&sd->dacl->aces[i].access_mask,
4511 &printer_generic_mapping);
4515 void map_job_permissions(struct security_descriptor *sd)
4519 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4520 se_map_generic(&sd->dacl->aces[i].access_mask,
4521 &job_generic_mapping);
4526 /****************************************************************************
4527 Check a user has permissions to perform the given operation. We use the
4528 permission constants defined in include/rpc_spoolss.h to check the various
4529 actions we perform when checking printer access.
4531 PRINTER_ACCESS_ADMINISTER:
4532 print_queue_pause, print_queue_resume, update_printer_sec,
4533 update_printer, spoolss_addprinterex_level_2,
4534 _spoolss_setprinterdata
4539 JOB_ACCESS_ADMINISTER:
4540 print_job_delete, print_job_pause, print_job_resume,
4543 Try access control in the following order (for performance reasons):
4544 1) root and SE_PRINT_OPERATOR can do anything (easy check)
4545 2) check security descriptor (bit comparisons in memory)
4546 3) "printer admins" (may result in numerous calls to winbind)
4548 ****************************************************************************/
4549 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
4552 struct spoolss_security_descriptor *secdesc = NULL;
4553 uint32 access_granted;
4558 TALLOC_CTX *mem_ctx = NULL;
4559 SE_PRIV se_printop = SE_PRINT_OPERATOR;
4561 /* If user is NULL then use the current_user structure */
4563 /* Always allow root or SE_PRINT_OPERATROR to do anything */
4565 if (server_info->utok.uid == sec_initial_uid()
4566 || user_has_privileges(server_info->ptok, &se_printop ) ) {
4570 /* Get printer name */
4572 pname = lp_printername(snum);
4574 if (!pname || !*pname) {
4579 /* Get printer security descriptor */
4581 if(!(mem_ctx = talloc_init("print_access_check"))) {
4586 result = winreg_get_printer_secdesc(mem_ctx,
4590 if (!W_ERROR_IS_OK(result)) {
4591 talloc_destroy(mem_ctx);
4596 if (access_type == JOB_ACCESS_ADMINISTER) {
4597 struct spoolss_security_descriptor *parent_secdesc = secdesc;
4599 /* Create a child security descriptor to check permissions
4600 against. This is because print jobs are child objects
4601 objects of a printer. */
4602 status = se_create_child_secdesc(mem_ctx,
4606 parent_secdesc->owner_sid,
4607 parent_secdesc->group_sid,
4609 if (!NT_STATUS_IS_OK(status)) {
4610 talloc_destroy(mem_ctx);
4611 errno = map_errno_from_nt_status(status);
4615 map_job_permissions(secdesc);
4617 map_printer_permissions(secdesc);
4621 status = se_access_check(secdesc, server_info->ptok, access_type,
4624 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
4626 /* see if we need to try the printer admin list */
4628 if (!NT_STATUS_IS_OK(status) &&
4629 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
4630 server_info->info3->base.domain.string,
4631 NULL, server_info->ptok,
4632 lp_printer_admin(snum)))) {
4633 talloc_destroy(mem_ctx);
4637 talloc_destroy(mem_ctx);
4639 if (!NT_STATUS_IS_OK(status)) {
4643 return NT_STATUS_IS_OK(status);
4646 /****************************************************************************
4647 Check the time parameters allow a print operation.
4648 *****************************************************************************/
4650 bool print_time_access_check(struct auth_serversupplied_info *server_info,
4651 const char *servicename)
4653 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4656 time_t now = time(NULL);
4660 result = winreg_get_printer(NULL, server_info,
4661 NULL, servicename, &pinfo2);
4662 if (!W_ERROR_IS_OK(result)) {
4666 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
4671 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4673 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
4677 TALLOC_FREE(pinfo2);
4686 void nt_printer_remove(TALLOC_CTX *mem_ctx,
4687 struct auth_serversupplied_info *server_info,
4688 const char *printer)
4692 result = winreg_delete_printer_key(mem_ctx, server_info, printer, "");
4693 if (!W_ERROR_IS_OK(result)) {
4694 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",