rap: use rap_LogonHours in rap_NetUserInfo11 as well.
[Samba/ekacnet.git] / source3 / printing / nt_printing.c
blob42ea5fb7c4e71be0813d6913a05a4c64dec64e00
1 /*
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/>.
22 #include "includes.h"
23 #include "librpc/gen_ndr/messaging.h"
24 #include "printing/pcap.h"
25 #include "registry.h"
26 #include "registry/reg_objects.h"
28 static TDB_CONTEXT *tdb_forms; /* used for forms files */
29 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
30 static TDB_CONTEXT *tdb_printers; /* used for printers files */
32 #define FORMS_PREFIX "FORMS/"
33 #define DRIVERS_PREFIX "DRIVERS/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
41 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
42 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
44 /* Map generic permissions to printer object specific permissions */
46 const struct generic_mapping printer_generic_mapping = {
47 PRINTER_READ,
48 PRINTER_WRITE,
49 PRINTER_EXECUTE,
50 PRINTER_ALL_ACCESS
53 const struct standard_mapping printer_std_mapping = {
54 PRINTER_READ,
55 PRINTER_WRITE,
56 PRINTER_EXECUTE,
57 PRINTER_ALL_ACCESS
60 /* Map generic permissions to print server object specific permissions */
62 const struct generic_mapping printserver_generic_mapping = {
63 SERVER_READ,
64 SERVER_WRITE,
65 SERVER_EXECUTE,
66 SERVER_ALL_ACCESS
69 const struct generic_mapping printserver_std_mapping = {
70 SERVER_READ,
71 SERVER_WRITE,
72 SERVER_EXECUTE,
73 SERVER_ALL_ACCESS
76 /* Map generic permissions to job object specific permissions */
78 const struct generic_mapping job_generic_mapping = {
79 JOB_READ,
80 JOB_WRITE,
81 JOB_EXECUTE,
82 JOB_ALL_ACCESS
85 /* We need one default form to support our default printer. Msoft adds the
86 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
87 array index). Letter is always first, so (for the current code) additions
88 always put things in the correct order. */
89 static const nt_forms_struct default_forms[] = {
90 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
91 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
92 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
93 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
94 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
95 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
96 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
97 {"A0",0x1,0xcd528,0x122488,0x0,0x0,0xcd528,0x122488},
98 {"A1",0x1,0x91050,0xcd528,0x0,0x0,0x91050,0xcd528},
99 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
100 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
101 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
102 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
103 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
104 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
105 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
106 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
107 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
108 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
109 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
110 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
111 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
112 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
113 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
114 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
115 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
116 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
117 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
118 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
119 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
120 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
121 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
122 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
123 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
124 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
125 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
126 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
127 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
128 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
129 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
130 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
131 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
132 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
133 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
134 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
135 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
136 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
137 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
138 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
139 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
140 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
141 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
142 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
143 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
144 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
145 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
146 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
147 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
148 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
149 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
150 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
151 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
152 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
153 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
154 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
155 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
156 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
157 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
158 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
159 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
160 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
161 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
162 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
163 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
164 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
165 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
166 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
167 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
168 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
169 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
170 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
171 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
172 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
173 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
174 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
175 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
176 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
177 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
178 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
179 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
180 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
181 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
182 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
183 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
184 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
185 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
186 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
187 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
188 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
189 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
190 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
191 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
192 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
193 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
194 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
195 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
196 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
197 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
198 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
199 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
200 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
201 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
202 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
203 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
204 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
205 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
206 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
207 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
208 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
209 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
212 static const struct print_architecture_table_node archi_table[]= {
214 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
215 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
216 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
217 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
218 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
219 {"Windows IA64", SPL_ARCH_IA64, 3 },
220 {"Windows x64", SPL_ARCH_X64, 3 },
221 {NULL, "", -1 }
225 /****************************************************************************
226 generate a new TDB_DATA key for storing a printer
227 ****************************************************************************/
229 static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
231 fstring share;
232 char *keystr = NULL;
233 TDB_DATA key;
235 fstrcpy(share, sharename);
236 strlower_m(share);
238 keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
239 key = string_term_tdb_data(keystr ? keystr : "");
241 return key;
244 /****************************************************************************
245 generate a new TDB_DATA key for storing a printer security descriptor
246 ****************************************************************************/
248 static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
249 const char* sharename )
251 fstring share;
252 char *keystr = NULL;
253 TDB_DATA key;
255 fstrcpy(share, sharename );
256 strlower_m(share);
258 keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
259 key = string_term_tdb_data(keystr ? keystr : "");
261 return key;
264 /****************************************************************************
265 ****************************************************************************/
267 static bool upgrade_to_version_3(void)
269 TDB_DATA kbuf, newkey, dbuf;
271 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
273 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
274 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
276 dbuf = tdb_fetch(tdb_drivers, kbuf);
278 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
279 DEBUG(0,("upgrade_to_version_3:moving form\n"));
280 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
281 SAFE_FREE(dbuf.dptr);
282 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
283 return False;
285 if (tdb_delete(tdb_drivers, kbuf) != 0) {
286 SAFE_FREE(dbuf.dptr);
287 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
288 return False;
292 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
293 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
294 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
295 SAFE_FREE(dbuf.dptr);
296 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
297 return False;
299 if (tdb_delete(tdb_drivers, kbuf) != 0) {
300 SAFE_FREE(dbuf.dptr);
301 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
302 return False;
306 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
307 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
308 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
309 SAFE_FREE(dbuf.dptr);
310 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
311 return False;
313 if (tdb_delete(tdb_drivers, kbuf) != 0) {
314 SAFE_FREE(dbuf.dptr);
315 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
316 return False;
320 SAFE_FREE(dbuf.dptr);
323 return True;
326 /*******************************************************************
327 Fix an issue with security descriptors. Printer sec_desc must
328 use more than the generic bits that were previously used
329 in <= 3.0.14a. They must also have a owner and group SID assigned.
330 Otherwise, any printers than have been migrated to a Windows
331 host using printmig.exe will not be accessible.
332 *******************************************************************/
334 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
335 TDB_DATA data, void *state )
337 NTSTATUS status;
338 struct sec_desc_buf *sd_orig = NULL;
339 struct sec_desc_buf *sd_new, *sd_store;
340 struct security_descriptor *sec, *new_sec;
341 TALLOC_CTX *ctx = state;
342 int result, i;
343 uint32 sd_size;
344 size_t size_new_sec;
346 if (!data.dptr || data.dsize == 0) {
347 return 0;
350 if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
351 return 0;
354 /* upgrade the security descriptor */
356 status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
357 if (!NT_STATUS_IS_OK(status)) {
358 /* delete bad entries */
359 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
360 (const char *)key.dptr ));
361 tdb_delete( tdb_printers, key );
362 return 0;
365 if (!sd_orig) {
366 return 0;
368 sec = sd_orig->sd;
370 /* is this even valid? */
372 if ( !sec->dacl ) {
373 return 0;
376 /* update access masks */
378 for ( i=0; i<sec->dacl->num_aces; i++ ) {
379 switch ( sec->dacl->aces[i].access_mask ) {
380 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
381 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
382 break;
384 case GENERIC_ALL_ACCESS:
385 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
386 break;
388 case READ_CONTROL_ACCESS:
389 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
391 default: /* no change */
392 break;
396 /* create a new struct security_descriptor with the appropriate owner and group SIDs */
398 new_sec = make_sec_desc( ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
399 &global_sid_Builtin_Administrators,
400 &global_sid_Builtin_Administrators,
401 NULL, NULL, &size_new_sec );
402 if (!new_sec) {
403 return 0;
405 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
406 if (!sd_new) {
407 return 0;
410 if ( !(sd_store = sec_desc_merge_buf( ctx, sd_new, sd_orig )) ) {
411 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
412 return 0;
415 /* store it back */
417 sd_size = ndr_size_security_descriptor(sd_store->sd, 0)
418 + sizeof(struct sec_desc_buf);
420 status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
421 if (!NT_STATUS_IS_OK(status)) {
422 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
423 return 0;
426 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
428 /* 0 to continue and non-zero to stop traversal */
430 return (result == -1);
433 /*******************************************************************
434 *******************************************************************/
436 static bool upgrade_to_version_4(void)
438 TALLOC_CTX *ctx;
439 int result;
441 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
443 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
444 return False;
446 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
448 talloc_destroy( ctx );
450 return ( result != -1 );
453 /*******************************************************************
454 Fix an issue with security descriptors. Printer sec_desc must
455 use more than the generic bits that were previously used
456 in <= 3.0.14a. They must also have a owner and group SID assigned.
457 Otherwise, any printers than have been migrated to a Windows
458 host using printmig.exe will not be accessible.
459 *******************************************************************/
461 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
462 TDB_DATA data, void *state )
464 TALLOC_CTX *ctx = talloc_tos();
465 TDB_DATA new_key;
467 if (!data.dptr || data.dsize == 0)
468 return 0;
470 /* upgrade printer records and security descriptors */
472 if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
473 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
475 else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
476 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
478 else {
479 /* ignore this record */
480 return 0;
483 /* delete the original record and store under the normalized key */
485 if ( tdb_delete( the_tdb, key ) != 0 ) {
486 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
487 key.dptr));
488 return 1;
491 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
492 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
493 key.dptr));
494 return 1;
497 return 0;
500 /*******************************************************************
501 *******************************************************************/
503 static bool upgrade_to_version_5(void)
505 TALLOC_CTX *ctx;
506 int result;
508 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
510 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
511 return False;
513 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
515 talloc_destroy( ctx );
517 return ( result != -1 );
520 /****************************************************************************
521 Open the NT printing tdbs. Done once before fork().
522 ****************************************************************************/
524 bool nt_printing_init(struct messaging_context *msg_ctx)
526 const char *vstring = "INFO/version";
527 WERROR win_rc;
528 int32 vers_id;
530 if ( tdb_drivers && tdb_printers && tdb_forms )
531 return True;
533 if (tdb_drivers)
534 tdb_close(tdb_drivers);
535 tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
536 if (!tdb_drivers) {
537 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
538 state_path("ntdrivers.tdb"), strerror(errno) ));
539 return False;
542 if (tdb_printers)
543 tdb_close(tdb_printers);
544 tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
545 if (!tdb_printers) {
546 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
547 state_path("ntprinters.tdb"), strerror(errno) ));
548 return False;
551 if (tdb_forms)
552 tdb_close(tdb_forms);
553 tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
554 if (!tdb_forms) {
555 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
556 state_path("ntforms.tdb"), strerror(errno) ));
557 return False;
560 /* handle a Samba upgrade */
562 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
563 if (vers_id == -1) {
564 DEBUG(10, ("Fresh database\n"));
565 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
566 vers_id = NTDRIVERS_DATABASE_VERSION_5;
569 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
571 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
572 if (!upgrade_to_version_3())
573 return False;
574 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
575 vers_id = NTDRIVERS_DATABASE_VERSION_3;
578 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
579 /* Written on a bigendian machine with old fetch_int code. Save as le. */
580 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
581 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
582 vers_id = NTDRIVERS_DATABASE_VERSION_3;
585 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
586 if ( !upgrade_to_version_4() )
587 return False;
588 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
589 vers_id = NTDRIVERS_DATABASE_VERSION_4;
592 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
593 if ( !upgrade_to_version_5() )
594 return False;
595 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
596 vers_id = NTDRIVERS_DATABASE_VERSION_5;
600 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
601 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
602 return False;
606 update_c_setprinter(True);
609 * register callback to handle updating printers as new
610 * drivers are installed
613 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
614 do_drv_upgrade_printer);
616 /* of course, none of the message callbacks matter if you don't
617 tell messages.c that you interested in receiving PRINT_GENERAL
618 msgs. This is done in serverid_register() */
621 if ( lp_security() == SEC_ADS ) {
622 win_rc = check_published_printers();
623 if (!W_ERROR_IS_OK(win_rc))
624 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
627 return True;
630 /*******************************************************************
631 Function to allow filename parsing "the old way".
632 ********************************************************************/
634 static NTSTATUS driver_unix_convert(connection_struct *conn,
635 const char *old_name,
636 struct smb_filename **smb_fname)
638 NTSTATUS status;
639 TALLOC_CTX *ctx = talloc_tos();
640 char *name = talloc_strdup(ctx, old_name);
642 if (!name) {
643 return NT_STATUS_NO_MEMORY;
645 unix_format(name);
646 name = unix_clean_name(ctx, name);
647 if (!name) {
648 return NT_STATUS_NO_MEMORY;
650 trim_string(name,"/","/");
652 status = unix_convert(ctx, conn, name, smb_fname, 0);
653 if (!NT_STATUS_IS_OK(status)) {
654 return NT_STATUS_NO_MEMORY;
657 return NT_STATUS_OK;
660 /*******************************************************************
661 tdb traversal function for counting printers.
662 ********************************************************************/
664 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
665 TDB_DATA data, void *context)
667 int *printer_count = (int*)context;
669 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
670 (*printer_count)++;
671 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
674 return 0;
677 /*******************************************************************
678 Update the spooler global c_setprinter. This variable is initialized
679 when the parent smbd starts with the number of existing printers. It
680 is monotonically increased by the current number of printers *after*
681 each add or delete printer RPC. Only Microsoft knows why... JRR020119
682 ********************************************************************/
684 uint32 update_c_setprinter(bool initialize)
686 int32 c_setprinter;
687 int32 printer_count = 0;
689 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
691 /* Traverse the tdb, counting the printers */
692 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
694 /* If initializing, set c_setprinter to current printers count
695 * otherwise, bump it by the current printer count
697 if (!initialize)
698 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
699 else
700 c_setprinter = printer_count;
702 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
703 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
705 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
707 return (uint32)c_setprinter;
710 /*******************************************************************
711 Get the spooler global c_setprinter, accounting for initialization.
712 ********************************************************************/
714 uint32 get_c_setprinter(void)
716 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
718 if (c_setprinter == (int32)-1)
719 c_setprinter = update_c_setprinter(True);
721 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
723 return (uint32)c_setprinter;
726 /****************************************************************************
727 Get builtin form struct list.
728 ****************************************************************************/
730 int get_builtin_ntforms(nt_forms_struct **list)
732 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
733 if (!*list) {
734 return 0;
736 return ARRAY_SIZE(default_forms);
739 /****************************************************************************
740 get a builtin form struct
741 ****************************************************************************/
743 bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
745 int i;
746 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
747 for (i=0; i<ARRAY_SIZE(default_forms); i++) {
748 if (strequal(form_name,default_forms[i].name)) {
749 DEBUGADD(6,("Found builtin form %s \n", form_name));
750 memcpy(form,&default_forms[i],sizeof(*form));
751 return true;
755 return false;
758 /****************************************************************************
759 get a form struct list.
760 ****************************************************************************/
762 int get_ntforms(nt_forms_struct **list)
764 TDB_DATA kbuf, newkey, dbuf;
765 nt_forms_struct form;
766 int ret;
767 int i;
768 int n = 0;
770 *list = NULL;
772 for (kbuf = tdb_firstkey(tdb_forms);
773 kbuf.dptr;
774 newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
776 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
777 continue;
779 dbuf = tdb_fetch(tdb_forms, kbuf);
780 if (!dbuf.dptr)
781 continue;
783 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
784 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
785 &i, &form.flag, &form.width, &form.length, &form.left,
786 &form.top, &form.right, &form.bottom);
787 SAFE_FREE(dbuf.dptr);
788 if (ret != dbuf.dsize)
789 continue;
791 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
792 if (!*list) {
793 DEBUG(0,("get_ntforms: Realloc fail.\n"));
794 return 0;
796 (*list)[n] = form;
797 n++;
801 return n;
804 /****************************************************************************
805 write a form struct list
806 ****************************************************************************/
808 int write_ntforms(nt_forms_struct **list, int number)
810 TALLOC_CTX *ctx = talloc_tos();
811 char *buf = NULL;
812 char *key = NULL;
813 int len;
814 TDB_DATA dbuf;
815 int i;
817 for (i=0;i<number;i++) {
818 /* save index, so list is rebuilt in correct order */
819 len = tdb_pack(NULL, 0, "dddddddd",
820 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
821 (*list)[i].left, (*list)[i].top, (*list)[i].right,
822 (*list)[i].bottom);
823 if (!len) {
824 continue;
826 buf = TALLOC_ARRAY(ctx, char, len);
827 if (!buf) {
828 return 0;
830 len = tdb_pack((uint8 *)buf, len, "dddddddd",
831 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
832 (*list)[i].left, (*list)[i].top, (*list)[i].right,
833 (*list)[i].bottom);
834 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
835 if (!key) {
836 return 0;
838 dbuf.dsize = len;
839 dbuf.dptr = (uint8 *)buf;
840 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
841 TALLOC_FREE(key);
842 TALLOC_FREE(buf);
843 break;
845 TALLOC_FREE(key);
846 TALLOC_FREE(buf);
849 return i;
852 /****************************************************************************
853 add a form struct at the end of the list
854 ****************************************************************************/
855 bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count)
857 int n=0;
858 bool update;
861 * NT tries to add forms even when
862 * they are already in the base
863 * only update the values if already present
866 update=False;
868 for (n=0; n<*count; n++) {
869 if ( strequal((*list)[n].name, form->form_name) ) {
870 update=True;
871 break;
875 if (update==False) {
876 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
877 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
878 return False;
880 fstrcpy((*list)[n].name, form->form_name);
881 (*count)++;
884 (*list)[n].flag = form->flags;
885 (*list)[n].width = form->size.width;
886 (*list)[n].length = form->size.height;
887 (*list)[n].left = form->area.left;
888 (*list)[n].top = form->area.top;
889 (*list)[n].right = form->area.right;
890 (*list)[n].bottom = form->area.bottom;
892 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
893 update ? "updated" : "added", form->form_name));
895 return True;
898 /****************************************************************************
899 Delete a named form struct.
900 ****************************************************************************/
902 bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
904 char *key = NULL;
905 int n=0;
907 *ret = WERR_OK;
909 for (n=0; n<*count; n++) {
910 if (!strncmp((*list)[n].name, del_name, strlen(del_name))) {
911 DEBUG(103, ("delete_a_form, [%s] in list\n", del_name));
912 break;
916 if (n == *count) {
917 DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
918 *ret = WERR_INVALID_FORM_NAME;
919 return False;
922 if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
923 *ret = WERR_NOMEM;
924 return false;
926 if (tdb_delete_bystring(tdb_forms, key) != 0) {
927 SAFE_FREE(key);
928 *ret = WERR_NOMEM;
929 return False;
931 SAFE_FREE(key);
932 return true;
935 /****************************************************************************
936 Update a form struct.
937 ****************************************************************************/
939 void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
941 int n=0;
943 DEBUG(106, ("[%s]\n", form->form_name));
944 for (n=0; n<count; n++) {
945 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
946 if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name)))
947 break;
950 if (n==count) return;
952 (*list)[n].flag = form->flags;
953 (*list)[n].width = form->size.width;
954 (*list)[n].length = form->size.height;
955 (*list)[n].left = form->area.left;
956 (*list)[n].top = form->area.top;
957 (*list)[n].right = form->area.right;
958 (*list)[n].bottom = form->area.bottom;
961 /****************************************************************************
962 Get the nt drivers list.
963 Traverse the database and look-up the matching names.
964 ****************************************************************************/
965 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
967 int total=0;
968 const char *short_archi;
969 char *key = NULL;
970 TDB_DATA kbuf, newkey;
972 short_archi = get_short_archi(architecture);
973 if (!short_archi) {
974 return 0;
977 if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
978 short_archi, version) < 0) {
979 return 0;
982 for (kbuf = tdb_firstkey(tdb_drivers);
983 kbuf.dptr;
984 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
986 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
987 continue;
989 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
990 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
991 SAFE_FREE(key);
992 return -1;
995 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
996 total++;
999 SAFE_FREE(key);
1000 return(total);
1003 /****************************************************************************
1004 Function to do the mapping between the long architecture name and
1005 the short one.
1006 ****************************************************************************/
1008 const char *get_short_archi(const char *long_archi)
1010 int i=-1;
1012 DEBUG(107,("Getting architecture dependant directory\n"));
1013 do {
1014 i++;
1015 } while ( (archi_table[i].long_archi!=NULL ) &&
1016 StrCaseCmp(long_archi, archi_table[i].long_archi) );
1018 if (archi_table[i].long_archi==NULL) {
1019 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1020 return NULL;
1023 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1025 DEBUGADD(108,("index: [%d]\n", i));
1026 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1027 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1029 return archi_table[i].short_archi;
1032 /****************************************************************************
1033 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1034 There are two case to be covered here: PE (Portable Executable) and NE (New
1035 Executable) files. Both files support the same INFO structure, but PE files
1036 store the signature in unicode, and NE files store it as !unicode.
1037 returns -1 on error, 1 on version info found, and 0 on no version info found.
1038 ****************************************************************************/
1040 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1042 int i;
1043 char *buf = NULL;
1044 ssize_t byte_count;
1046 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1047 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1048 fname, DOS_HEADER_SIZE));
1049 goto error_exit;
1052 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1053 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1054 fname, (unsigned long)byte_count));
1055 goto no_version_info;
1058 /* Is this really a DOS header? */
1059 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1060 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1061 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1062 goto no_version_info;
1065 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1066 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1067 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1068 fname, errno));
1069 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1070 goto no_version_info;
1073 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1074 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1075 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1076 fname, (unsigned long)byte_count));
1077 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1078 goto no_version_info;
1081 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1082 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1083 unsigned int num_sections;
1084 unsigned int section_table_bytes;
1086 /* Just skip over optional header to get to section table */
1087 if (SMB_VFS_LSEEK(fsp,
1088 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1089 SEEK_CUR) == (SMB_OFF_T)-1) {
1090 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1091 fname, errno));
1092 goto error_exit;
1095 /* get the section table */
1096 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1097 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1098 if (section_table_bytes == 0)
1099 goto error_exit;
1101 SAFE_FREE(buf);
1102 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1103 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1104 fname, section_table_bytes));
1105 goto error_exit;
1108 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1109 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1110 fname, (unsigned long)byte_count));
1111 goto error_exit;
1114 /* Iterate the section table looking for the resource section ".rsrc" */
1115 for (i = 0; i < num_sections; i++) {
1116 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1118 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1119 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1120 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1122 if (section_bytes == 0)
1123 goto error_exit;
1125 SAFE_FREE(buf);
1126 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1127 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1128 fname, section_bytes));
1129 goto error_exit;
1132 /* Seek to the start of the .rsrc section info */
1133 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1134 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1135 fname, errno));
1136 goto error_exit;
1139 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1140 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1141 fname, (unsigned long)byte_count));
1142 goto error_exit;
1145 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1146 goto error_exit;
1148 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1149 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1150 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1151 /* Align to next long address */
1152 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1154 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1155 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1156 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1158 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1159 fname, *major, *minor,
1160 (*major>>16)&0xffff, *major&0xffff,
1161 (*minor>>16)&0xffff, *minor&0xffff));
1162 SAFE_FREE(buf);
1163 return 1;
1170 /* Version info not found, fall back to origin date/time */
1171 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1172 SAFE_FREE(buf);
1173 return 0;
1175 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1176 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1177 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1178 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1179 /* At this point, we assume the file is in error. It still could be somthing
1180 * else besides a NE file, but it unlikely at this point. */
1181 goto error_exit;
1184 /* Allocate a bit more space to speed up things */
1185 SAFE_FREE(buf);
1186 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1187 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1188 fname, PE_HEADER_SIZE));
1189 goto error_exit;
1192 /* This is a HACK! I got tired of trying to sort through the messy
1193 * 'NE' file format. If anyone wants to clean this up please have at
1194 * it, but this works. 'NE' files will eventually fade away. JRR */
1195 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1196 /* Cover case that should not occur in a well formed 'NE' .dll file */
1197 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1199 for(i=0; i<byte_count; i++) {
1200 /* Fast skip past data that can't possibly match */
1201 if (buf[i] != 'V') continue;
1203 /* Potential match data crosses buf boundry, move it to beginning
1204 * of buf, and fill the buf with as much as it will hold. */
1205 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1206 int bc;
1208 memcpy(buf, &buf[i], byte_count-i);
1209 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1210 (byte_count-i))) < 0) {
1212 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1213 fname, errno));
1214 goto error_exit;
1217 byte_count = bc + (byte_count - i);
1218 if (byte_count<VS_VERSION_INFO_SIZE) break;
1220 i = 0;
1223 /* Check that the full signature string and the magic number that
1224 * follows exist (not a perfect solution, but the chances that this
1225 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1226 * twice, as it is simpler to read the code. */
1227 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1228 /* Compute skip alignment to next long address */
1229 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1230 sizeof(VS_SIGNATURE)) & 3;
1231 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1233 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1234 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1235 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1236 fname, *major, *minor,
1237 (*major>>16)&0xffff, *major&0xffff,
1238 (*minor>>16)&0xffff, *minor&0xffff));
1239 SAFE_FREE(buf);
1240 return 1;
1245 /* Version info not found, fall back to origin date/time */
1246 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1247 SAFE_FREE(buf);
1248 return 0;
1250 } else
1251 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1252 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1253 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1255 no_version_info:
1256 SAFE_FREE(buf);
1257 return 0;
1259 error_exit:
1260 SAFE_FREE(buf);
1261 return -1;
1264 /****************************************************************************
1265 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1266 share one or more files. During the MS installation process files are checked
1267 to insure that only a newer version of a shared file is installed over an
1268 older version. There are several possibilities for this comparison. If there
1269 is no previous version, the new one is newer (obviously). If either file is
1270 missing the version info structure, compare the creation date (on Unix use
1271 the modification date). Otherwise chose the numerically larger version number.
1272 ****************************************************************************/
1274 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1276 bool use_version = true;
1278 uint32 new_major;
1279 uint32 new_minor;
1280 time_t new_create_time;
1282 uint32 old_major;
1283 uint32 old_minor;
1284 time_t old_create_time;
1286 struct smb_filename *smb_fname = NULL;
1287 files_struct *fsp = NULL;
1288 SMB_STRUCT_STAT st;
1290 NTSTATUS status;
1291 int ret;
1293 SET_STAT_INVALID(st);
1294 new_create_time = (time_t)0;
1295 old_create_time = (time_t)0;
1297 /* Get file version info (if available) for previous file (if it exists) */
1298 status = driver_unix_convert(conn, old_file, &smb_fname);
1299 if (!NT_STATUS_IS_OK(status)) {
1300 goto error_exit;
1303 status = SMB_VFS_CREATE_FILE(
1304 conn, /* conn */
1305 NULL, /* req */
1306 0, /* root_dir_fid */
1307 smb_fname, /* fname */
1308 FILE_GENERIC_READ, /* access_mask */
1309 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1310 FILE_OPEN, /* create_disposition*/
1311 0, /* create_options */
1312 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1313 INTERNAL_OPEN_ONLY, /* oplock_request */
1314 0, /* allocation_size */
1315 0, /* private_flags */
1316 NULL, /* sd */
1317 NULL, /* ea_list */
1318 &fsp, /* result */
1319 NULL); /* pinfo */
1321 if (!NT_STATUS_IS_OK(status)) {
1322 /* Old file not found, so by definition new file is in fact newer */
1323 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
1324 "errno = %d\n", smb_fname_str_dbg(smb_fname),
1325 errno));
1326 ret = 1;
1327 goto done;
1329 } else {
1330 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1331 if (ret == -1) {
1332 goto error_exit;
1335 if (!ret) {
1336 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1337 old_file));
1338 use_version = false;
1339 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1340 goto error_exit;
1342 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1343 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1344 (long)old_create_time));
1347 close_file(NULL, fsp, NORMAL_CLOSE);
1348 fsp = NULL;
1350 /* Get file version info (if available) for new file */
1351 status = driver_unix_convert(conn, new_file, &smb_fname);
1352 if (!NT_STATUS_IS_OK(status)) {
1353 goto error_exit;
1356 status = SMB_VFS_CREATE_FILE(
1357 conn, /* conn */
1358 NULL, /* req */
1359 0, /* root_dir_fid */
1360 smb_fname, /* fname */
1361 FILE_GENERIC_READ, /* access_mask */
1362 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1363 FILE_OPEN, /* create_disposition*/
1364 0, /* create_options */
1365 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1366 INTERNAL_OPEN_ONLY, /* oplock_request */
1367 0, /* allocation_size */
1368 0, /* private_flags */
1369 NULL, /* sd */
1370 NULL, /* ea_list */
1371 &fsp, /* result */
1372 NULL); /* pinfo */
1374 if (!NT_STATUS_IS_OK(status)) {
1375 /* New file not found, this shouldn't occur if the caller did its job */
1376 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
1377 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
1378 goto error_exit;
1380 } else {
1381 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1382 if (ret == -1) {
1383 goto error_exit;
1386 if (!ret) {
1387 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1388 new_file));
1389 use_version = false;
1390 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1391 goto error_exit;
1393 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1394 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1395 (long)new_create_time));
1398 close_file(NULL, fsp, NORMAL_CLOSE);
1399 fsp = NULL;
1401 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1402 /* Compare versions and choose the larger version number */
1403 if (new_major > old_major ||
1404 (new_major == old_major && new_minor > old_minor)) {
1406 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1407 ret = 1;
1408 goto done;
1410 else {
1411 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1412 ret = 0;
1413 goto done;
1416 } else {
1417 /* Compare modification time/dates and choose the newest time/date */
1418 if (new_create_time > old_create_time) {
1419 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1420 ret = 1;
1421 goto done;
1423 else {
1424 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1425 ret = 0;
1426 goto done;
1430 error_exit:
1431 if(fsp)
1432 close_file(NULL, fsp, NORMAL_CLOSE);
1433 ret = -1;
1434 done:
1435 TALLOC_FREE(smb_fname);
1436 return ret;
1439 /****************************************************************************
1440 Determine the correct cVersion associated with an architecture and driver
1441 ****************************************************************************/
1442 static uint32 get_correct_cversion(struct pipes_struct *p,
1443 const char *architecture,
1444 const char *driverpath_in,
1445 WERROR *perr)
1447 int cversion;
1448 NTSTATUS nt_status;
1449 struct smb_filename *smb_fname = NULL;
1450 char *driverpath = NULL;
1451 files_struct *fsp = NULL;
1452 connection_struct *conn = NULL;
1453 NTSTATUS status;
1454 char *oldcwd;
1455 fstring printdollar;
1456 int printdollar_snum;
1458 *perr = WERR_INVALID_PARAM;
1460 /* If architecture is Windows 95/98/ME, the version is always 0. */
1461 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1462 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1463 *perr = WERR_OK;
1464 return 0;
1467 /* If architecture is Windows x64, the version is always 3. */
1468 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1469 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1470 *perr = WERR_OK;
1471 return 3;
1474 fstrcpy(printdollar, "print$");
1476 printdollar_snum = find_service(printdollar);
1477 if (printdollar_snum == -1) {
1478 *perr = WERR_NO_SUCH_SHARE;
1479 return -1;
1482 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1483 lp_pathname(printdollar_snum),
1484 p->server_info, &oldcwd);
1485 if (!NT_STATUS_IS_OK(nt_status)) {
1486 DEBUG(0,("get_correct_cversion: create_conn_struct "
1487 "returned %s\n", nt_errstr(nt_status)));
1488 *perr = ntstatus_to_werror(nt_status);
1489 return -1;
1492 /* Open the driver file (Portable Executable format) and determine the
1493 * deriver the cversion. */
1494 driverpath = talloc_asprintf(talloc_tos(),
1495 "%s/%s",
1496 architecture,
1497 driverpath_in);
1498 if (!driverpath) {
1499 *perr = WERR_NOMEM;
1500 goto error_exit;
1503 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
1504 if (!NT_STATUS_IS_OK(nt_status)) {
1505 *perr = ntstatus_to_werror(nt_status);
1506 goto error_exit;
1509 nt_status = vfs_file_exist(conn, smb_fname);
1510 if (!NT_STATUS_IS_OK(nt_status)) {
1511 *perr = WERR_BADFILE;
1512 goto error_exit;
1515 status = SMB_VFS_CREATE_FILE(
1516 conn, /* conn */
1517 NULL, /* req */
1518 0, /* root_dir_fid */
1519 smb_fname, /* fname */
1520 FILE_GENERIC_READ, /* access_mask */
1521 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1522 FILE_OPEN, /* create_disposition*/
1523 0, /* create_options */
1524 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1525 INTERNAL_OPEN_ONLY, /* oplock_request */
1526 0, /* private_flags */
1527 0, /* allocation_size */
1528 NULL, /* sd */
1529 NULL, /* ea_list */
1530 &fsp, /* result */
1531 NULL); /* pinfo */
1533 if (!NT_STATUS_IS_OK(status)) {
1534 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1535 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1536 *perr = WERR_ACCESS_DENIED;
1537 goto error_exit;
1538 } else {
1539 uint32 major;
1540 uint32 minor;
1541 int ret;
1543 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1544 if (ret == -1) goto error_exit;
1546 if (!ret) {
1547 DEBUG(6,("get_correct_cversion: Version info not "
1548 "found [%s]\n",
1549 smb_fname_str_dbg(smb_fname)));
1550 goto error_exit;
1554 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1555 * for more details. Version in this case is not just the version of the
1556 * file, but the version in the sense of kernal mode (2) vs. user mode
1557 * (3) drivers. Other bits of the version fields are the version info.
1558 * JRR 010716
1560 cversion = major & 0x0000ffff;
1561 switch (cversion) {
1562 case 2: /* WinNT drivers */
1563 case 3: /* Win2K drivers */
1564 break;
1566 default:
1567 DEBUG(6,("get_correct_cversion: cversion "
1568 "invalid [%s] cversion = %d\n",
1569 smb_fname_str_dbg(smb_fname),
1570 cversion));
1571 goto error_exit;
1574 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1575 " = 0x%x minor = 0x%x\n",
1576 smb_fname_str_dbg(smb_fname), major, minor));
1579 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1580 smb_fname_str_dbg(smb_fname), cversion));
1582 goto done;
1584 error_exit:
1585 cversion = -1;
1586 done:
1587 TALLOC_FREE(smb_fname);
1588 if (fsp != NULL) {
1589 close_file(NULL, fsp, NORMAL_CLOSE);
1591 if (conn != NULL) {
1592 vfs_ChDir(conn, oldcwd);
1593 conn_free(conn);
1595 if (cversion != -1) {
1596 *perr = WERR_OK;
1598 return cversion;
1601 /****************************************************************************
1602 ****************************************************************************/
1604 #define strip_driver_path(_mem_ctx, _element) do { \
1605 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1606 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1607 W_ERROR_HAVE_NO_MEMORY((_element)); \
1609 } while (0);
1611 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1612 struct pipes_struct *rpc_pipe,
1613 const char *architecture,
1614 const char **driver_path,
1615 const char **data_file,
1616 const char **config_file,
1617 const char **help_file,
1618 struct spoolss_StringArray *dependent_files,
1619 uint32_t *version)
1621 const char *short_architecture;
1622 int i;
1623 WERROR err;
1624 char *_p;
1626 if (!*driver_path || !*data_file || !*config_file) {
1627 return WERR_INVALID_PARAM;
1630 /* clean up the driver name.
1631 * we can get .\driver.dll
1632 * or worse c:\windows\system\driver.dll !
1634 /* using an intermediate string to not have overlaping memcpy()'s */
1636 strip_driver_path(mem_ctx, *driver_path);
1637 strip_driver_path(mem_ctx, *data_file);
1638 strip_driver_path(mem_ctx, *config_file);
1639 if (help_file) {
1640 strip_driver_path(mem_ctx, *help_file);
1643 if (dependent_files && dependent_files->string) {
1644 for (i=0; dependent_files->string[i]; i++) {
1645 strip_driver_path(mem_ctx, dependent_files->string[i]);
1649 short_architecture = get_short_archi(architecture);
1650 if (!short_architecture) {
1651 return WERR_UNKNOWN_PRINTER_DRIVER;
1654 /* jfm:7/16/2000 the client always sends the cversion=0.
1655 * The server should check which version the driver is by reading
1656 * the PE header of driver->driverpath.
1658 * For Windows 95/98 the version is 0 (so the value sent is correct)
1659 * For Windows NT (the architecture doesn't matter)
1660 * NT 3.1: cversion=0
1661 * NT 3.5/3.51: cversion=1
1662 * NT 4: cversion=2
1663 * NT2K: cversion=3
1666 *version = get_correct_cversion(rpc_pipe, short_architecture,
1667 *driver_path, &err);
1668 if (*version == -1) {
1669 return err;
1672 return WERR_OK;
1675 /****************************************************************************
1676 ****************************************************************************/
1678 WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe,
1679 struct spoolss_AddDriverInfoCtr *r)
1681 switch (r->level) {
1682 case 3:
1683 return clean_up_driver_struct_level(r, rpc_pipe,
1684 r->info.info3->architecture,
1685 &r->info.info3->driver_path,
1686 &r->info.info3->data_file,
1687 &r->info.info3->config_file,
1688 &r->info.info3->help_file,
1689 r->info.info3->dependent_files,
1690 &r->info.info3->version);
1691 case 6:
1692 return clean_up_driver_struct_level(r, rpc_pipe,
1693 r->info.info6->architecture,
1694 &r->info.info6->driver_path,
1695 &r->info.info6->data_file,
1696 &r->info.info6->config_file,
1697 &r->info.info6->help_file,
1698 r->info.info6->dependent_files,
1699 &r->info.info6->version);
1700 default:
1701 return WERR_NOT_SUPPORTED;
1705 /****************************************************************************
1706 This function sucks and should be replaced. JRA.
1707 ****************************************************************************/
1709 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1710 const struct spoolss_AddDriverInfo6 *src)
1712 dst->version = src->version;
1714 dst->driver_name = src->driver_name;
1715 dst->architecture = src->architecture;
1716 dst->driver_path = src->driver_path;
1717 dst->data_file = src->data_file;
1718 dst->config_file = src->config_file;
1719 dst->help_file = src->help_file;
1720 dst->monitor_name = src->monitor_name;
1721 dst->default_datatype = src->default_datatype;
1722 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1723 dst->dependent_files = src->dependent_files;
1726 /****************************************************************************
1727 This function sucks and should be replaced. JRA.
1728 ****************************************************************************/
1730 static void convert_level_8_to_level3(TALLOC_CTX *mem_ctx,
1731 struct spoolss_AddDriverInfo3 *dst,
1732 const struct spoolss_DriverInfo8 *src)
1734 dst->version = src->version;
1735 dst->driver_name = src->driver_name;
1736 dst->architecture = src->architecture;
1737 dst->driver_path = src->driver_path;
1738 dst->data_file = src->data_file;
1739 dst->config_file = src->config_file;
1740 dst->help_file = src->help_file;
1741 dst->monitor_name = src->monitor_name;
1742 dst->default_datatype = src->default_datatype;
1743 if (src->dependent_files) {
1744 dst->dependent_files = talloc_zero(mem_ctx, struct spoolss_StringArray);
1745 if (!dst->dependent_files) return;
1746 dst->dependent_files->string = src->dependent_files;
1747 } else {
1748 dst->dependent_files = NULL;
1752 /****************************************************************************
1753 ****************************************************************************/
1755 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1756 connection_struct *conn,
1757 const char *driver_file,
1758 const char *short_architecture,
1759 uint32_t driver_version,
1760 uint32_t version)
1762 struct smb_filename *smb_fname_old = NULL;
1763 struct smb_filename *smb_fname_new = NULL;
1764 char *old_name = NULL;
1765 char *new_name = NULL;
1766 NTSTATUS status;
1767 WERROR ret;
1769 old_name = talloc_asprintf(mem_ctx, "%s/%s",
1770 short_architecture, driver_file);
1771 W_ERROR_HAVE_NO_MEMORY(old_name);
1773 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1774 short_architecture, driver_version, driver_file);
1775 if (new_name == NULL) {
1776 TALLOC_FREE(old_name);
1777 return WERR_NOMEM;
1780 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1782 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1783 if (!NT_STATUS_IS_OK(status)) {
1784 ret = WERR_NOMEM;
1785 goto out;
1788 /* Setup a synthetic smb_filename struct */
1789 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
1790 if (!smb_fname_new) {
1791 ret = WERR_NOMEM;
1792 goto out;
1795 smb_fname_new->base_name = new_name;
1797 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1798 "'%s'\n", smb_fname_old->base_name,
1799 smb_fname_new->base_name));
1801 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1802 OPENX_FILE_EXISTS_TRUNCATE |
1803 OPENX_FILE_CREATE_IF_NOT_EXIST,
1804 0, false);
1806 if (!NT_STATUS_IS_OK(status)) {
1807 DEBUG(0,("move_driver_file_to_download_area: Unable "
1808 "to rename [%s] to [%s]: %s\n",
1809 smb_fname_old->base_name, new_name,
1810 nt_errstr(status)));
1811 ret = WERR_ACCESS_DENIED;
1812 goto out;
1816 ret = WERR_OK;
1817 out:
1818 TALLOC_FREE(smb_fname_old);
1819 TALLOC_FREE(smb_fname_new);
1820 return ret;
1823 WERROR move_driver_to_download_area(struct pipes_struct *p,
1824 struct spoolss_AddDriverInfoCtr *r,
1825 WERROR *perr)
1827 struct spoolss_AddDriverInfo3 *driver;
1828 struct spoolss_AddDriverInfo3 converted_driver;
1829 const char *short_architecture;
1830 struct smb_filename *smb_dname = NULL;
1831 char *new_dir = NULL;
1832 connection_struct *conn = NULL;
1833 NTSTATUS nt_status;
1834 int i;
1835 TALLOC_CTX *ctx = talloc_tos();
1836 int ver = 0;
1837 char *oldcwd;
1838 fstring printdollar;
1839 int printdollar_snum;
1841 *perr = WERR_OK;
1843 switch (r->level) {
1844 case 3:
1845 driver = r->info.info3;
1846 break;
1847 case 6:
1848 convert_level_6_to_level3(&converted_driver, r->info.info6);
1849 driver = &converted_driver;
1850 break;
1851 default:
1852 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1853 return WERR_UNKNOWN_LEVEL;
1856 short_architecture = get_short_archi(driver->architecture);
1857 if (!short_architecture) {
1858 return WERR_UNKNOWN_PRINTER_DRIVER;
1861 fstrcpy(printdollar, "print$");
1863 printdollar_snum = find_service(printdollar);
1864 if (printdollar_snum == -1) {
1865 *perr = WERR_NO_SUCH_SHARE;
1866 return WERR_NO_SUCH_SHARE;
1869 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1870 lp_pathname(printdollar_snum),
1871 p->server_info, &oldcwd);
1872 if (!NT_STATUS_IS_OK(nt_status)) {
1873 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1874 "returned %s\n", nt_errstr(nt_status)));
1875 *perr = ntstatus_to_werror(nt_status);
1876 return *perr;
1879 new_dir = talloc_asprintf(ctx,
1880 "%s/%d",
1881 short_architecture,
1882 driver->version);
1883 if (!new_dir) {
1884 *perr = WERR_NOMEM;
1885 goto err_exit;
1887 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1888 if (!NT_STATUS_IS_OK(nt_status)) {
1889 *perr = WERR_NOMEM;
1890 goto err_exit;
1893 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1895 create_directory(conn, NULL, smb_dname);
1897 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1898 * listed for this driver which has already been moved, skip it (note:
1899 * drivers may list the same file name several times. Then check if the
1900 * file already exists in archi\version\, if so, check that the version
1901 * info (or time stamps if version info is unavailable) is newer (or the
1902 * date is later). If it is, move it to archi\version\filexxx.yyy.
1903 * Otherwise, delete the file.
1905 * If a file is not moved to archi\version\ because of an error, all the
1906 * rest of the 'unmoved' driver files are removed from archi\. If one or
1907 * more of the driver's files was already moved to archi\version\, it
1908 * potentially leaves the driver in a partially updated state. Version
1909 * trauma will most likely occur if an client attempts to use any printer
1910 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1911 * done is appropriate... later JRR
1914 DEBUG(5,("Moving files now !\n"));
1916 if (driver->driver_path && strlen(driver->driver_path)) {
1918 *perr = move_driver_file_to_download_area(ctx,
1919 conn,
1920 driver->driver_path,
1921 short_architecture,
1922 driver->version,
1923 ver);
1924 if (!W_ERROR_IS_OK(*perr)) {
1925 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1926 ver = -1;
1928 goto err_exit;
1932 if (driver->data_file && strlen(driver->data_file)) {
1933 if (!strequal(driver->data_file, driver->driver_path)) {
1935 *perr = move_driver_file_to_download_area(ctx,
1936 conn,
1937 driver->data_file,
1938 short_architecture,
1939 driver->version,
1940 ver);
1941 if (!W_ERROR_IS_OK(*perr)) {
1942 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1943 ver = -1;
1945 goto err_exit;
1950 if (driver->config_file && strlen(driver->config_file)) {
1951 if (!strequal(driver->config_file, driver->driver_path) &&
1952 !strequal(driver->config_file, driver->data_file)) {
1954 *perr = move_driver_file_to_download_area(ctx,
1955 conn,
1956 driver->config_file,
1957 short_architecture,
1958 driver->version,
1959 ver);
1960 if (!W_ERROR_IS_OK(*perr)) {
1961 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1962 ver = -1;
1964 goto err_exit;
1969 if (driver->help_file && strlen(driver->help_file)) {
1970 if (!strequal(driver->help_file, driver->driver_path) &&
1971 !strequal(driver->help_file, driver->data_file) &&
1972 !strequal(driver->help_file, driver->config_file)) {
1974 *perr = move_driver_file_to_download_area(ctx,
1975 conn,
1976 driver->help_file,
1977 short_architecture,
1978 driver->version,
1979 ver);
1980 if (!W_ERROR_IS_OK(*perr)) {
1981 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1982 ver = -1;
1984 goto err_exit;
1989 if (driver->dependent_files && driver->dependent_files->string) {
1990 for (i=0; driver->dependent_files->string[i]; i++) {
1991 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1992 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1993 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1994 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1995 int j;
1996 for (j=0; j < i; j++) {
1997 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1998 goto NextDriver;
2002 *perr = move_driver_file_to_download_area(ctx,
2003 conn,
2004 driver->dependent_files->string[i],
2005 short_architecture,
2006 driver->version,
2007 ver);
2008 if (!W_ERROR_IS_OK(*perr)) {
2009 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
2010 ver = -1;
2012 goto err_exit;
2015 NextDriver: ;
2019 err_exit:
2020 TALLOC_FREE(smb_dname);
2022 if (conn != NULL) {
2023 vfs_ChDir(conn, oldcwd);
2024 conn_free(conn);
2027 if (W_ERROR_EQUAL(*perr, WERR_OK)) {
2028 return WERR_OK;
2030 if (ver == -1) {
2031 return WERR_UNKNOWN_PRINTER_DRIVER;
2033 return (*perr);
2036 /****************************************************************************
2037 ****************************************************************************/
2039 static uint32 add_a_printer_driver_3(struct spoolss_AddDriverInfo3 *driver)
2041 TALLOC_CTX *ctx = talloc_tos();
2042 int len, buflen;
2043 const char *architecture;
2044 char *directory = NULL;
2045 char *key = NULL;
2046 uint8 *buf;
2047 int i, ret;
2048 TDB_DATA dbuf;
2050 architecture = get_short_archi(driver->architecture);
2051 if (!architecture) {
2052 return (uint32)-1;
2055 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2056 * \\server is added in the rpc server layer.
2057 * It does make sense to NOT store the server's name in the printer TDB.
2060 directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
2061 architecture, driver->version);
2062 if (!directory) {
2063 return (uint32)-1;
2066 #define gen_full_driver_unc_path(ctx, directory, file) \
2067 do { \
2068 if (file && strlen(file)) { \
2069 file = talloc_asprintf(ctx, "%s%s", directory, file); \
2070 } else { \
2071 file = talloc_strdup(ctx, ""); \
2073 if (!file) { \
2074 return (uint32_t)-1; \
2076 } while (0);
2078 /* .inf files do not always list a file for each of the four standard files.
2079 * Don't prepend a path to a null filename, or client claims:
2080 * "The server on which the printer resides does not have a suitable
2081 * <printer driver name> printer driver installed. Click OK if you
2082 * wish to install the driver on your local machine."
2085 gen_full_driver_unc_path(ctx, directory, driver->driver_path);
2086 gen_full_driver_unc_path(ctx, directory, driver->data_file);
2087 gen_full_driver_unc_path(ctx, directory, driver->config_file);
2088 gen_full_driver_unc_path(ctx, directory, driver->help_file);
2090 if (driver->dependent_files && driver->dependent_files->string) {
2091 for (i=0; driver->dependent_files->string[i]; i++) {
2092 gen_full_driver_unc_path(ctx, directory,
2093 driver->dependent_files->string[i]);
2097 key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
2098 architecture, driver->version, driver->driver_name);
2099 if (!key) {
2100 return (uint32)-1;
2103 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
2105 buf = NULL;
2106 len = buflen = 0;
2108 again:
2109 len = 0;
2110 len += tdb_pack(buf+len, buflen-len, "dffffffff",
2111 driver->version,
2112 driver->driver_name,
2113 driver->architecture,
2114 driver->driver_path,
2115 driver->data_file,
2116 driver->config_file,
2117 driver->help_file,
2118 driver->monitor_name ? driver->monitor_name : "",
2119 driver->default_datatype ? driver->default_datatype : "");
2121 if (driver->dependent_files && driver->dependent_files->string) {
2122 for (i=0; driver->dependent_files->string[i]; i++) {
2123 len += tdb_pack(buf+len, buflen-len, "f",
2124 driver->dependent_files->string[i]);
2128 if (len != buflen) {
2129 buf = (uint8 *)SMB_REALLOC(buf, len);
2130 if (!buf) {
2131 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2132 ret = -1;
2133 goto done;
2135 buflen = len;
2136 goto again;
2139 dbuf.dptr = buf;
2140 dbuf.dsize = len;
2142 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2144 done:
2145 if (ret)
2146 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2148 SAFE_FREE(buf);
2149 return ret;
2152 /****************************************************************************
2153 ****************************************************************************/
2155 static uint32_t add_a_printer_driver_8(struct spoolss_DriverInfo8 *driver)
2157 TALLOC_CTX *mem_ctx = talloc_new(talloc_tos());
2158 struct spoolss_AddDriverInfo3 info3;
2159 uint32_t ret;
2161 convert_level_8_to_level3(mem_ctx, &info3, driver);
2163 ret = add_a_printer_driver_3(&info3);
2164 talloc_free(mem_ctx);
2166 return ret;
2169 /****************************************************************************
2170 ****************************************************************************/
2172 static WERROR get_a_printer_driver_3_default(TALLOC_CTX *mem_ctx,
2173 struct spoolss_DriverInfo3 *info,
2174 const char *driver, const char *arch)
2176 info->driver_name = talloc_strdup(mem_ctx, driver);
2177 if (!info->driver_name) {
2178 return WERR_NOMEM;
2181 info->default_datatype = talloc_strdup(mem_ctx, "RAW");
2182 if (!info->default_datatype) {
2183 return WERR_NOMEM;
2186 info->driver_path = talloc_strdup(mem_ctx, "");
2187 info->data_file = talloc_strdup(mem_ctx, "");
2188 info->config_file = talloc_strdup(mem_ctx, "");
2189 info->help_file = talloc_strdup(mem_ctx, "");
2190 if (!info->driver_path || !info->data_file || !info->config_file || !info->help_file) {
2191 return WERR_NOMEM;
2194 return WERR_OK;
2197 /****************************************************************************
2198 ****************************************************************************/
2200 static WERROR get_a_printer_driver_3(TALLOC_CTX *mem_ctx,
2201 struct spoolss_DriverInfo3 *driver,
2202 const char *drivername, const char *arch,
2203 uint32_t version)
2205 TDB_DATA dbuf;
2206 const char *architecture;
2207 int len = 0;
2208 int i;
2209 char *key = NULL;
2210 fstring name, driverpath, environment, datafile, configfile, helpfile, monitorname, defaultdatatype;
2212 architecture = get_short_archi(arch);
2213 if ( !architecture ) {
2214 return WERR_UNKNOWN_PRINTER_DRIVER;
2217 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2219 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2220 version = 0;
2222 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2224 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
2225 architecture, version, drivername) < 0) {
2226 return WERR_NOMEM;
2229 dbuf = tdb_fetch_bystring(tdb_drivers, key);
2230 if (!dbuf.dptr) {
2231 SAFE_FREE(key);
2232 return WERR_UNKNOWN_PRINTER_DRIVER;
2235 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2236 &driver->version,
2237 name,
2238 environment,
2239 driverpath,
2240 datafile,
2241 configfile,
2242 helpfile,
2243 monitorname,
2244 defaultdatatype);
2246 driver->driver_name = talloc_strdup(mem_ctx, name);
2247 driver->architecture = talloc_strdup(mem_ctx, environment);
2248 driver->driver_path = talloc_strdup(mem_ctx, driverpath);
2249 driver->data_file = talloc_strdup(mem_ctx, datafile);
2250 driver->config_file = talloc_strdup(mem_ctx, configfile);
2251 driver->help_file = talloc_strdup(mem_ctx, helpfile);
2252 driver->monitor_name = talloc_strdup(mem_ctx, monitorname);
2253 driver->default_datatype = talloc_strdup(mem_ctx, defaultdatatype);
2255 i=0;
2257 while (len < dbuf.dsize) {
2259 fstring file;
2261 driver->dependent_files = talloc_realloc(mem_ctx, driver->dependent_files, const char *, i+2);
2262 if (!driver->dependent_files ) {
2263 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2264 break;
2267 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2268 &file);
2270 driver->dependent_files[i] = talloc_strdup(mem_ctx, file);
2272 i++;
2275 if (driver->dependent_files)
2276 driver->dependent_files[i] = NULL;
2278 SAFE_FREE(dbuf.dptr);
2279 SAFE_FREE(key);
2281 if (len != dbuf.dsize) {
2282 return get_a_printer_driver_3_default(mem_ctx, driver, drivername, arch);
2285 return WERR_OK;
2288 /****************************************************************************
2289 ****************************************************************************/
2290 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2292 int len = 0;
2294 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2296 if (!nt_devmode)
2297 return len;
2299 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2300 nt_devmode->devicename,
2301 nt_devmode->formname,
2303 nt_devmode->specversion,
2304 nt_devmode->driverversion,
2305 nt_devmode->size,
2306 nt_devmode->driverextra,
2307 nt_devmode->orientation,
2308 nt_devmode->papersize,
2309 nt_devmode->paperlength,
2310 nt_devmode->paperwidth,
2311 nt_devmode->scale,
2312 nt_devmode->copies,
2313 nt_devmode->defaultsource,
2314 nt_devmode->printquality,
2315 nt_devmode->color,
2316 nt_devmode->duplex,
2317 nt_devmode->yresolution,
2318 nt_devmode->ttoption,
2319 nt_devmode->collate,
2320 nt_devmode->logpixels,
2322 nt_devmode->fields,
2323 nt_devmode->bitsperpel,
2324 nt_devmode->pelswidth,
2325 nt_devmode->pelsheight,
2326 nt_devmode->displayflags,
2327 nt_devmode->displayfrequency,
2328 nt_devmode->icmmethod,
2329 nt_devmode->icmintent,
2330 nt_devmode->mediatype,
2331 nt_devmode->dithertype,
2332 nt_devmode->reserved1,
2333 nt_devmode->reserved2,
2334 nt_devmode->panningwidth,
2335 nt_devmode->panningheight,
2336 nt_devmode->nt_dev_private);
2338 if (nt_devmode->nt_dev_private) {
2339 len += tdb_pack(buf+len, buflen-len, "B",
2340 nt_devmode->driverextra,
2341 nt_devmode->nt_dev_private);
2344 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2346 return len;
2349 /****************************************************************************
2350 Pack all values in all printer keys
2351 ***************************************************************************/
2353 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2355 int len = 0;
2356 int i, j;
2357 struct regval_blob *val;
2358 struct regval_ctr *val_ctr;
2359 char *path = NULL;
2360 int num_values;
2362 if ( !data )
2363 return 0;
2365 /* loop over all keys */
2367 for ( i=0; i<data->num_keys; i++ ) {
2368 val_ctr = data->keys[i].values;
2369 num_values = regval_ctr_numvals( val_ctr );
2371 /* pack the keyname followed by a empty value */
2373 len += tdb_pack(buf+len, buflen-len, "pPdB",
2374 &data->keys[i].name,
2375 data->keys[i].name,
2376 REG_NONE,
2378 NULL);
2380 /* now loop over all values */
2382 for ( j=0; j<num_values; j++ ) {
2383 /* pathname should be stored as <key>\<value> */
2385 val = regval_ctr_specific_value( val_ctr, j );
2386 if (asprintf(&path, "%s\\%s",
2387 data->keys[i].name,
2388 regval_name(val)) < 0) {
2389 return -1;
2392 len += tdb_pack(buf+len, buflen-len, "pPdB",
2393 val,
2394 path,
2395 regval_type(val),
2396 regval_size(val),
2397 regval_data_p(val) );
2399 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2400 SAFE_FREE(path);
2405 /* terminator */
2407 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2409 return len;
2413 /****************************************************************************
2414 Delete a printer - this just deletes the printer info file, any open
2415 handles are not affected.
2416 ****************************************************************************/
2418 uint32 del_a_printer(const char *sharename)
2420 TDB_DATA kbuf;
2421 char *printdb_path = NULL;
2422 TALLOC_CTX *ctx = talloc_tos();
2424 kbuf = make_printer_tdbkey(ctx, sharename);
2425 tdb_delete(tdb_printers, kbuf);
2427 kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2428 tdb_delete(tdb_printers, kbuf);
2430 close_all_print_db();
2432 if (geteuid() == sec_initial_uid()) {
2433 if (asprintf(&printdb_path, "%s%s.tdb",
2434 cache_path("printing/"),
2435 sharename) < 0) {
2436 return (uint32)-1;
2438 unlink(printdb_path);
2439 SAFE_FREE(printdb_path);
2442 return 0;
2445 /****************************************************************************
2446 ****************************************************************************/
2447 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2449 uint8 *buf;
2450 int buflen, len;
2451 int retlen;
2452 WERROR ret;
2453 TDB_DATA kbuf, dbuf;
2456 * in addprinter: no servername and the printer is the name
2457 * in setprinter: servername is \\server
2458 * and printer is \\server\\printer
2460 * Samba manages only local printers.
2461 * we currently don't support things like i
2462 * path=\\other_server\printer
2464 * We only store the printername, not \\server\printername
2467 if ( info->servername[0] != '\0' ) {
2468 trim_string(info->printername, info->servername, NULL);
2469 trim_char(info->printername, '\\', '\0');
2470 info->servername[0]='\0';
2474 * JFM: one day I'll forget.
2475 * below that's info->portname because that's the SAMBA sharename
2476 * and I made NT 'thinks' it's the portname
2477 * the info->sharename is the thing you can name when you add a printer
2478 * that's the short-name when you create shared printer for 95/98
2479 * So I've made a limitation in SAMBA: you can only have 1 printer model
2480 * behind a SAMBA share.
2483 buf = NULL;
2484 buflen = 0;
2486 again:
2487 len = 0;
2488 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2489 info->attributes,
2490 info->priority,
2491 info->default_priority,
2492 info->starttime,
2493 info->untiltime,
2494 info->status,
2495 info->cjobs,
2496 info->averageppm,
2497 info->changeid,
2498 info->c_setprinter,
2499 info->setuptime,
2500 info->servername,
2501 info->printername,
2502 info->sharename,
2503 info->portname,
2504 info->drivername,
2505 info->comment,
2506 info->location,
2507 info->sepfile,
2508 info->printprocessor,
2509 info->datatype,
2510 info->parameters);
2512 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2513 retlen = pack_values( info->data, buf+len, buflen-len );
2514 if (retlen == -1) {
2515 ret = WERR_NOMEM;
2516 goto done;
2518 len += retlen;
2520 if (buflen != len) {
2521 buf = (uint8 *)SMB_REALLOC(buf, len);
2522 if (!buf) {
2523 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2524 ret = WERR_NOMEM;
2525 goto done;
2527 buflen = len;
2528 goto again;
2531 kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2533 dbuf.dptr = buf;
2534 dbuf.dsize = len;
2536 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2538 done:
2539 if (!W_ERROR_IS_OK(ret))
2540 DEBUG(8, ("error updating printer to tdb on disk\n"));
2542 SAFE_FREE(buf);
2544 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2545 info->sharename, info->drivername, info->portname, len));
2547 return ret;
2550 /****************************************************************************
2551 Create and allocate a default devicemode.
2552 ****************************************************************************/
2554 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
2555 const char *devicename,
2556 struct spoolss_DeviceMode **devmode)
2558 struct spoolss_DeviceMode *dm;
2559 char *dname;
2561 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2562 if (dm == NULL) {
2563 return WERR_NOMEM;
2566 dname = talloc_asprintf(dm, "%s", devicename);
2567 if (dname == NULL) {
2568 return WERR_NOMEM;
2570 if (strlen(dname) > MAXDEVICENAME) {
2571 dname[MAXDEVICENAME] = '\0';
2573 dm->devicename = dname;
2575 dm->formname = talloc_strdup(dm, "Letter");
2576 if (dm->formname == NULL) {
2577 return WERR_NOMEM;
2580 dm->specversion = DMSPEC_NT4_AND_ABOVE;
2581 dm->driverversion = 0x0400;
2582 dm->size = 0x00DC;
2583 dm->__driverextra_length = 0;
2584 dm->fields = DEVMODE_FORMNAME |
2585 DEVMODE_TTOPTION |
2586 DEVMODE_PRINTQUALITY |
2587 DEVMODE_DEFAULTSOURCE |
2588 DEVMODE_COPIES |
2589 DEVMODE_SCALE |
2590 DEVMODE_PAPERSIZE |
2591 DEVMODE_ORIENTATION;
2592 dm->orientation = DMORIENT_PORTRAIT;
2593 dm->papersize = DMPAPER_LETTER;
2594 dm->paperlength = 0;
2595 dm->paperwidth = 0;
2596 dm->scale = 0x64;
2597 dm->copies = 1;
2598 dm->defaultsource = DMBIN_FORMSOURCE;
2599 dm->printquality = DMRES_HIGH; /* 0x0258 */
2600 dm->color = DMRES_MONOCHROME;
2601 dm->duplex = DMDUP_SIMPLEX;
2602 dm->yresolution = 0;
2603 dm->ttoption = DMTT_SUBDEV;
2604 dm->collate = DMCOLLATE_FALSE;
2605 dm->icmmethod = 0;
2606 dm->icmintent = 0;
2607 dm->mediatype = 0;
2608 dm->dithertype = 0;
2610 dm->logpixels = 0;
2611 dm->bitsperpel = 0;
2612 dm->pelswidth = 0;
2613 dm->pelsheight = 0;
2614 dm->displayflags = 0;
2615 dm->displayfrequency = 0;
2616 dm->reserved1 = 0;
2617 dm->reserved2 = 0;
2618 dm->panningwidth = 0;
2619 dm->panningheight = 0;
2621 dm->driverextra_data.data = NULL;
2622 dm->driverextra_data.length = 0;
2624 *devmode = dm;
2625 return WERR_OK;
2628 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
2629 struct spoolss_security_descriptor **secdesc)
2631 struct security_ace ace[5]; /* max number of ace entries */
2632 int i = 0;
2633 uint32_t sa;
2634 struct security_acl *psa = NULL;
2635 struct security_descriptor *psd = NULL;
2636 struct dom_sid adm_sid;
2637 size_t sd_size;
2639 /* Create an ACE where Everyone is allowed to print */
2641 sa = PRINTER_ACE_PRINT;
2642 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2643 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2645 /* Add the domain admins group if we are a DC */
2647 if ( IS_DC ) {
2648 struct dom_sid domadmins_sid;
2650 sid_compose(&domadmins_sid, get_global_sam_sid(),
2651 DOMAIN_RID_ADMINS);
2653 sa = PRINTER_ACE_FULL_CONTROL;
2654 init_sec_ace(&ace[i++], &domadmins_sid,
2655 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2656 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2657 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2658 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2660 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
2661 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
2663 sa = PRINTER_ACE_FULL_CONTROL;
2664 init_sec_ace(&ace[i++], &adm_sid,
2665 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2666 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2667 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2668 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2671 /* add BUILTIN\Administrators as FULL CONTROL */
2673 sa = PRINTER_ACE_FULL_CONTROL;
2674 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2675 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2676 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2677 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2678 SEC_ACE_TYPE_ACCESS_ALLOWED,
2679 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2681 /* Make the security descriptor owned by the BUILTIN\Administrators */
2683 /* The ACL revision number in rpc_secdesc.h differs from the one
2684 created by NT when setting ACE entries in printer
2685 descriptors. NT4 complains about the property being edited by a
2686 NT5 machine. */
2688 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
2689 psd = make_sec_desc(mem_ctx,
2690 SD_REVISION,
2691 SEC_DESC_SELF_RELATIVE,
2692 &global_sid_Builtin_Administrators,
2693 &global_sid_Builtin_Administrators,
2694 NULL,
2695 psa,
2696 &sd_size);
2699 if (psd == NULL) {
2700 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2701 return WERR_NOMEM;
2704 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2705 (unsigned int)sd_size));
2707 *secdesc = psd;
2709 return WERR_OK;
2712 /****************************************************************************
2713 Malloc and return an NT devicemode.
2714 ****************************************************************************/
2716 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2719 char adevice[MAXDEVICENAME];
2720 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2722 if (nt_devmode == NULL) {
2723 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2724 return NULL;
2727 ZERO_STRUCTP(nt_devmode);
2729 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2730 fstrcpy(nt_devmode->devicename, adevice);
2732 fstrcpy(nt_devmode->formname, "Letter");
2734 nt_devmode->specversion = DMSPEC_NT4_AND_ABOVE;
2735 nt_devmode->driverversion = 0x0400;
2736 nt_devmode->size = 0x00DC;
2737 nt_devmode->driverextra = 0x0000;
2738 nt_devmode->fields = DEVMODE_FORMNAME |
2739 DEVMODE_TTOPTION |
2740 DEVMODE_PRINTQUALITY |
2741 DEVMODE_DEFAULTSOURCE |
2742 DEVMODE_COPIES |
2743 DEVMODE_SCALE |
2744 DEVMODE_PAPERSIZE |
2745 DEVMODE_ORIENTATION;
2746 nt_devmode->orientation = DMORIENT_PORTRAIT;
2747 nt_devmode->papersize = DMPAPER_LETTER;
2748 nt_devmode->paperlength = 0;
2749 nt_devmode->paperwidth = 0;
2750 nt_devmode->scale = 0x64;
2751 nt_devmode->copies = 1;
2752 nt_devmode->defaultsource = DMBIN_FORMSOURCE;
2753 nt_devmode->printquality = DMRES_HIGH; /* 0x0258 */
2754 nt_devmode->color = DMRES_MONOCHROME;
2755 nt_devmode->duplex = DMDUP_SIMPLEX;
2756 nt_devmode->yresolution = 0;
2757 nt_devmode->ttoption = DMTT_SUBDEV;
2758 nt_devmode->collate = DMCOLLATE_FALSE;
2759 nt_devmode->icmmethod = 0;
2760 nt_devmode->icmintent = 0;
2761 nt_devmode->mediatype = 0;
2762 nt_devmode->dithertype = 0;
2764 /* non utilisés par un driver d'imprimante */
2765 nt_devmode->logpixels = 0;
2766 nt_devmode->bitsperpel = 0;
2767 nt_devmode->pelswidth = 0;
2768 nt_devmode->pelsheight = 0;
2769 nt_devmode->displayflags = 0;
2770 nt_devmode->displayfrequency = 0;
2771 nt_devmode->reserved1 = 0;
2772 nt_devmode->reserved2 = 0;
2773 nt_devmode->panningwidth = 0;
2774 nt_devmode->panningheight = 0;
2776 nt_devmode->nt_dev_private = NULL;
2777 return nt_devmode;
2780 /****************************************************************************
2781 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2782 ****************************************************************************/
2784 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2786 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2788 if(nt_devmode == NULL)
2789 return;
2791 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2793 SAFE_FREE(nt_devmode->nt_dev_private);
2794 SAFE_FREE(*devmode_ptr);
2797 /****************************************************************************
2798 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2799 ****************************************************************************/
2801 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2803 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2805 if ( !info )
2806 return;
2808 free_nt_devicemode(&info->devmode);
2810 TALLOC_FREE( *info_ptr );
2814 /****************************************************************************
2815 ****************************************************************************/
2816 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2818 int len = 0;
2819 int extra_len = 0;
2820 NT_DEVICEMODE devmode;
2822 ZERO_STRUCT(devmode);
2824 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2826 if (!*nt_devmode) return len;
2828 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2829 devmode.devicename,
2830 devmode.formname,
2832 &devmode.specversion,
2833 &devmode.driverversion,
2834 &devmode.size,
2835 &devmode.driverextra,
2836 &devmode.orientation,
2837 &devmode.papersize,
2838 &devmode.paperlength,
2839 &devmode.paperwidth,
2840 &devmode.scale,
2841 &devmode.copies,
2842 &devmode.defaultsource,
2843 &devmode.printquality,
2844 &devmode.color,
2845 &devmode.duplex,
2846 &devmode.yresolution,
2847 &devmode.ttoption,
2848 &devmode.collate,
2849 &devmode.logpixels,
2851 &devmode.fields,
2852 &devmode.bitsperpel,
2853 &devmode.pelswidth,
2854 &devmode.pelsheight,
2855 &devmode.displayflags,
2856 &devmode.displayfrequency,
2857 &devmode.icmmethod,
2858 &devmode.icmintent,
2859 &devmode.mediatype,
2860 &devmode.dithertype,
2861 &devmode.reserved1,
2862 &devmode.reserved2,
2863 &devmode.panningwidth,
2864 &devmode.panningheight,
2865 &devmode.nt_dev_private);
2867 if (devmode.nt_dev_private) {
2868 /* the len in tdb_unpack is an int value and
2869 * devmode.driverextra is only a short
2871 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2872 devmode.driverextra=(uint16)extra_len;
2874 /* check to catch an invalid TDB entry so we don't segfault */
2875 if (devmode.driverextra == 0) {
2876 devmode.nt_dev_private = NULL;
2880 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2881 if (!*nt_devmode) {
2882 SAFE_FREE(devmode.nt_dev_private);
2883 return -1;
2886 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2887 if (devmode.nt_dev_private)
2888 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2890 return len;
2893 /****************************************************************************
2894 Allocate and initialize a new slot.
2895 ***************************************************************************/
2897 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2899 NT_PRINTER_KEY *d;
2900 int key_index;
2901 WERROR werr;
2903 if ( !name || !data )
2904 return -1;
2906 /* allocate another slot in the NT_PRINTER_KEY array */
2908 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2909 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2910 return -1;
2913 data->keys = d;
2915 key_index = data->num_keys;
2917 /* initialze new key */
2919 data->keys[key_index].name = talloc_strdup( data, name );
2921 werr = regval_ctr_init(data, &(data->keys[key_index].values));
2922 if (!W_ERROR_IS_OK(werr)) {
2923 return -1;
2926 data->num_keys++;
2928 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2930 return key_index;
2933 /****************************************************************************
2934 search for a registry key name in the existing printer data
2935 ***************************************************************************/
2937 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2939 int i;
2941 for ( i=0; i<data->num_keys; i++ ) {
2942 if ( strequal( data->keys[i].name, name ) ) {
2944 /* cleanup memory */
2946 TALLOC_FREE( data->keys[i].name );
2947 TALLOC_FREE( data->keys[i].values );
2949 /* if not the end of the array, move remaining elements down one slot */
2951 data->num_keys--;
2952 if ( data->num_keys && (i < data->num_keys) )
2953 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2955 break;
2960 return data->num_keys;
2963 /****************************************************************************
2964 search for a registry key name in the existing printer data
2965 ***************************************************************************/
2967 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2969 int key_index = -1;
2970 int i;
2972 if ( !data || !name )
2973 return -1;
2975 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2977 /* loop over all existing keys */
2979 for ( i=0; i<data->num_keys; i++ ) {
2980 if ( strequal(data->keys[i].name, name) ) {
2981 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2982 key_index = i;
2983 break;
2988 return key_index;
2991 /****************************************************************************
2992 ***************************************************************************/
2994 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2996 int i, j;
2997 int key_len;
2998 int num_subkeys = 0;
2999 char *p;
3000 fstring *subkeys_ptr = NULL;
3001 fstring subkeyname;
3003 *subkeys = NULL;
3005 if ( !data )
3006 return 0;
3008 if ( !key )
3009 return -1;
3011 /* special case of asking for the top level printer data registry key names */
3013 if ( strlen(key) == 0 ) {
3014 for ( i=0; i<data->num_keys; i++ ) {
3016 /* found a match, so allocate space and copy the name */
3018 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3019 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3020 num_subkeys+1));
3021 return -1;
3024 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
3025 num_subkeys++;
3028 goto done;
3031 /* asking for the subkeys of some key */
3032 /* subkey paths are stored in the key name using '\' as the delimiter */
3034 for ( i=0; i<data->num_keys; i++ ) {
3035 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
3037 /* if we found the exact key, then break */
3038 key_len = strlen( key );
3039 if ( strlen(data->keys[i].name) == key_len )
3040 break;
3042 /* get subkey path */
3044 p = data->keys[i].name + key_len;
3045 if ( *p == '\\' )
3046 p++;
3047 fstrcpy( subkeyname, p );
3048 if ( (p = strchr( subkeyname, '\\' )) )
3049 *p = '\0';
3051 /* don't add a key more than once */
3053 for ( j=0; j<num_subkeys; j++ ) {
3054 if ( strequal( subkeys_ptr[j], subkeyname ) )
3055 break;
3058 if ( j != num_subkeys )
3059 continue;
3061 /* found a match, so allocate space and copy the name */
3063 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3064 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3065 num_subkeys+1));
3066 return 0;
3069 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
3070 num_subkeys++;
3075 /* return error if the key was not found */
3077 if ( i == data->num_keys ) {
3078 SAFE_FREE(subkeys_ptr);
3079 return -1;
3082 done:
3083 /* tag off the end */
3085 if (num_subkeys)
3086 fstrcpy(subkeys_ptr[num_subkeys], "" );
3088 *subkeys = subkeys_ptr;
3090 return num_subkeys;
3093 #ifdef HAVE_ADS
3094 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3095 const char *sz)
3097 regval_ctr_delvalue(ctr, val_name);
3098 regval_ctr_addvalue_sz(ctr, val_name, sz);
3101 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
3102 uint32 dword)
3104 regval_ctr_delvalue(ctr, val_name);
3105 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
3106 (uint8 *) &dword, sizeof(dword));
3109 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
3110 bool b)
3112 uint8 bin_bool = (b ? 1 : 0);
3113 regval_ctr_delvalue(ctr, val_name);
3114 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
3115 (uint8 *) &bin_bool, sizeof(bin_bool));
3118 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3119 const char *multi_sz)
3121 const char *a[2];
3123 a[0] = multi_sz;
3124 a[1] = NULL;
3126 regval_ctr_delvalue(ctr, val_name);
3127 regval_ctr_addvalue_multi_sz(ctr, val_name, a);
3130 /****************************************************************************
3131 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3133 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3134 * @return bool indicating success or failure
3135 ***************************************************************************/
3137 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
3139 struct regval_ctr *ctr = NULL;
3140 fstring longname;
3141 const char *dnssuffix;
3142 char *allocated_string = NULL;
3143 const char *ascii_str;
3144 int i;
3146 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3147 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3148 ctr = info2->data->keys[i].values;
3150 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3151 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3153 /* we make the assumption that the netbios name is the same
3154 as the DNS name sinc ethe former will be what we used to
3155 join the domain */
3157 dnssuffix = get_mydnsdomname(talloc_tos());
3158 if (dnssuffix && *dnssuffix) {
3159 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3160 } else {
3161 fstrcpy( longname, global_myname() );
3164 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3166 if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3167 return false;
3169 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3170 SAFE_FREE(allocated_string);
3172 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3173 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3174 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3175 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3176 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3177 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3178 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3179 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3180 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3182 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3183 (info2->attributes &
3184 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3186 switch (info2->attributes & 0x3) {
3187 case 0:
3188 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3189 break;
3190 case 1:
3191 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3192 break;
3193 case 2:
3194 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3195 break;
3196 default:
3197 ascii_str = "unknown";
3199 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3201 return True;
3204 /*****************************************************************
3205 ****************************************************************/
3207 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3208 struct GUID guid)
3210 int i;
3211 struct regval_ctr *ctr=NULL;
3213 /* find the DsSpooler key */
3214 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3215 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3216 ctr = info2->data->keys[i].values;
3218 regval_ctr_delvalue(ctr, "objectGUID");
3220 /* We used to store this as a REG_BINARY but that causes
3221 Vista to whine */
3223 regval_ctr_addvalue_sz(ctr, "objectGUID",
3224 GUID_string(talloc_tos(), &guid));
3227 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3228 NT_PRINTER_INFO_LEVEL *printer)
3230 ADS_STATUS ads_rc;
3231 LDAPMessage *res;
3232 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3233 char *srv_dn_utf8, **srv_cn_utf8;
3234 TALLOC_CTX *ctx;
3235 ADS_MODLIST mods;
3236 const char *attrs[] = {"objectGUID", NULL};
3237 struct GUID guid;
3238 WERROR win_rc = WERR_OK;
3239 size_t converted_size;
3241 /* build the ads mods */
3242 ctx = talloc_init("nt_printer_publish_ads");
3243 if (ctx == NULL) {
3244 return WERR_NOMEM;
3247 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3249 /* figure out where to publish */
3250 ads_find_machine_acct(ads, &res, global_myname());
3252 /* We use ldap_get_dn here as we need the answer
3253 * in utf8 to call ldap_explode_dn(). JRA. */
3255 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3256 if (!srv_dn_utf8) {
3257 TALLOC_FREE(ctx);
3258 return WERR_SERVER_UNAVAILABLE;
3260 ads_msgfree(ads, res);
3261 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3262 if (!srv_cn_utf8) {
3263 TALLOC_FREE(ctx);
3264 ldap_memfree(srv_dn_utf8);
3265 return WERR_SERVER_UNAVAILABLE;
3267 /* Now convert to CH_UNIX. */
3268 if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3269 TALLOC_FREE(ctx);
3270 ldap_memfree(srv_dn_utf8);
3271 ldap_memfree(srv_cn_utf8);
3272 return WERR_SERVER_UNAVAILABLE;
3274 if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3275 TALLOC_FREE(ctx);
3276 ldap_memfree(srv_dn_utf8);
3277 ldap_memfree(srv_cn_utf8);
3278 TALLOC_FREE(srv_dn);
3279 return WERR_SERVER_UNAVAILABLE;
3282 ldap_memfree(srv_dn_utf8);
3283 ldap_memfree(srv_cn_utf8);
3285 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3286 if (!srv_cn_escaped) {
3287 TALLOC_FREE(ctx);
3288 return WERR_SERVER_UNAVAILABLE;
3290 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3291 if (!sharename_escaped) {
3292 SAFE_FREE(srv_cn_escaped);
3293 TALLOC_FREE(ctx);
3294 return WERR_SERVER_UNAVAILABLE;
3297 prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3299 SAFE_FREE(srv_cn_escaped);
3300 SAFE_FREE(sharename_escaped);
3302 mods = ads_init_mods(ctx);
3304 if (mods == NULL) {
3305 SAFE_FREE(prt_dn);
3306 TALLOC_FREE(ctx);
3307 return WERR_NOMEM;
3310 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3311 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3312 printer->info_2->sharename);
3314 /* publish it */
3315 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3316 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3317 int i;
3318 for (i=0; mods[i] != 0; i++)
3320 mods[i] = (LDAPMod *)-1;
3321 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3324 if (!ADS_ERR_OK(ads_rc))
3325 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3327 /* retreive the guid and store it locally */
3328 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3329 ZERO_STRUCT(guid);
3330 ads_pull_guid(ads, res, &guid);
3331 ads_msgfree(ads, res);
3332 store_printer_guid(printer->info_2, guid);
3333 win_rc = mod_a_printer(printer, 2);
3335 TALLOC_FREE(ctx);
3337 return win_rc;
3340 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3341 NT_PRINTER_INFO_LEVEL *printer)
3343 ADS_STATUS ads_rc;
3344 LDAPMessage *res = NULL;
3345 char *prt_dn = NULL;
3347 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3349 /* remove the printer from the directory */
3350 ads_rc = ads_find_printer_on_server(ads, &res,
3351 printer->info_2->sharename, global_myname());
3353 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3354 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3355 if (!prt_dn) {
3356 ads_msgfree(ads, res);
3357 return WERR_NOMEM;
3359 ads_rc = ads_del_dn(ads, prt_dn);
3360 TALLOC_FREE(prt_dn);
3363 if (res) {
3364 ads_msgfree(ads, res);
3366 return WERR_OK;
3369 /****************************************************************************
3370 * Publish a printer in the directory
3372 * @param snum describing printer service
3373 * @return WERROR indicating status of publishing
3374 ***************************************************************************/
3376 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3378 ADS_STATUS ads_rc;
3379 ADS_STRUCT *ads = NULL;
3380 NT_PRINTER_INFO_LEVEL *printer = NULL;
3381 WERROR win_rc;
3383 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3384 if (!W_ERROR_IS_OK(win_rc))
3385 goto done;
3387 switch (action) {
3388 case DSPRINT_PUBLISH:
3389 case DSPRINT_UPDATE:
3390 /* set the DsSpooler info and attributes */
3391 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3392 win_rc = WERR_NOMEM;
3393 goto done;
3396 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3397 break;
3398 case DSPRINT_UNPUBLISH:
3399 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3400 break;
3401 default:
3402 win_rc = WERR_NOT_SUPPORTED;
3403 goto done;
3406 win_rc = mod_a_printer(printer, 2);
3407 if (!W_ERROR_IS_OK(win_rc)) {
3408 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3409 goto done;
3412 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3413 if (!ads) {
3414 DEBUG(3, ("ads_init() failed\n"));
3415 win_rc = WERR_SERVER_UNAVAILABLE;
3416 goto done;
3418 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3419 SAFE_FREE(ads->auth.password);
3420 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3421 NULL, NULL);
3423 /* ads_connect() will find the DC for us */
3424 ads_rc = ads_connect(ads);
3425 if (!ADS_ERR_OK(ads_rc)) {
3426 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3427 win_rc = WERR_ACCESS_DENIED;
3428 goto done;
3431 switch (action) {
3432 case DSPRINT_PUBLISH:
3433 case DSPRINT_UPDATE:
3434 win_rc = nt_printer_publish_ads(ads, printer);
3435 break;
3436 case DSPRINT_UNPUBLISH:
3437 win_rc = nt_printer_unpublish_ads(ads, printer);
3438 break;
3441 done:
3442 free_a_printer(&printer, 2);
3443 ads_destroy(&ads);
3444 return win_rc;
3447 WERROR check_published_printers(void)
3449 ADS_STATUS ads_rc;
3450 ADS_STRUCT *ads = NULL;
3451 int snum;
3452 int n_services = lp_numservices();
3453 NT_PRINTER_INFO_LEVEL *printer = NULL;
3455 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3456 if (!ads) {
3457 DEBUG(3, ("ads_init() failed\n"));
3458 return WERR_SERVER_UNAVAILABLE;
3460 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3461 SAFE_FREE(ads->auth.password);
3462 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3463 NULL, NULL);
3465 /* ads_connect() will find the DC for us */
3466 ads_rc = ads_connect(ads);
3467 if (!ADS_ERR_OK(ads_rc)) {
3468 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3469 ads_destroy(&ads);
3470 ads_kdestroy("MEMORY:prtpub_cache");
3471 return WERR_ACCESS_DENIED;
3474 for (snum = 0; snum < n_services; snum++) {
3475 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3476 continue;
3478 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3479 lp_servicename(snum))) &&
3480 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3481 nt_printer_publish_ads(ads, printer);
3483 free_a_printer(&printer, 2);
3486 ads_destroy(&ads);
3487 ads_kdestroy("MEMORY:prtpub_cache");
3488 return WERR_OK;
3491 bool is_printer_published(Printer_entry *print_hnd, int snum,
3492 struct GUID *guid)
3494 NT_PRINTER_INFO_LEVEL *printer = NULL;
3495 struct regval_ctr *ctr;
3496 struct regval_blob *guid_val;
3497 WERROR win_rc;
3498 int i;
3499 bool ret = False;
3500 DATA_BLOB blob;
3502 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3504 if (!W_ERROR_IS_OK(win_rc) ||
3505 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3506 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3507 !(ctr = printer->info_2->data->keys[i].values) ||
3508 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3510 free_a_printer(&printer, 2);
3511 return False;
3514 /* fetching printer guids really ought to be a separate function. */
3516 if ( guid ) {
3517 char *guid_str;
3519 /* We used to store the guid as REG_BINARY, then swapped
3520 to REG_SZ for Vista compatibility so check for both */
3522 switch ( regval_type(guid_val) ){
3523 case REG_SZ:
3524 blob = data_blob_const(regval_data_p(guid_val),
3525 regval_size(guid_val));
3526 pull_reg_sz(talloc_tos(), &blob, (const char **)&guid_str);
3527 ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3528 talloc_free(guid_str);
3529 break;
3530 case REG_BINARY:
3531 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3532 ret = False;
3533 break;
3535 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3536 break;
3537 default:
3538 DEBUG(0,("is_printer_published: GUID value stored as "
3539 "invaluid type (%d)\n", regval_type(guid_val) ));
3540 break;
3544 free_a_printer(&printer, 2);
3545 return ret;
3547 #else
3548 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3550 return WERR_OK;
3553 WERROR check_published_printers(void)
3555 return WERR_OK;
3558 bool is_printer_published(Printer_entry *print_hnd, int snum,
3559 struct GUID *guid)
3561 return False;
3563 #endif /* HAVE_ADS */
3565 /****************************************************************************
3566 ***************************************************************************/
3568 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3570 NT_PRINTER_DATA *data;
3571 int i;
3572 int removed_keys = 0;
3573 int empty_slot;
3575 data = p2->data;
3576 empty_slot = data->num_keys;
3578 if ( !key )
3579 return WERR_INVALID_PARAM;
3581 /* remove all keys */
3583 if ( !strlen(key) ) {
3585 TALLOC_FREE( data );
3587 p2->data = NULL;
3589 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3590 p2->printername ));
3592 return WERR_OK;
3595 /* remove a specific key (and all subkeys) */
3597 for ( i=0; i<data->num_keys; i++ ) {
3598 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3599 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3600 data->keys[i].name));
3602 TALLOC_FREE( data->keys[i].name );
3603 TALLOC_FREE( data->keys[i].values );
3605 /* mark the slot as empty */
3607 ZERO_STRUCTP( &data->keys[i] );
3611 /* find the first empty slot */
3613 for ( i=0; i<data->num_keys; i++ ) {
3614 if ( !data->keys[i].name ) {
3615 empty_slot = i;
3616 removed_keys++;
3617 break;
3621 if ( i == data->num_keys )
3622 /* nothing was removed */
3623 return WERR_INVALID_PARAM;
3625 /* move everything down */
3627 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3628 if ( data->keys[i].name ) {
3629 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3630 ZERO_STRUCTP( &data->keys[i] );
3631 empty_slot++;
3632 removed_keys++;
3636 /* update count */
3638 data->num_keys -= removed_keys;
3640 /* sanity check to see if anything is left */
3642 if ( !data->num_keys ) {
3643 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3645 SAFE_FREE( data->keys );
3646 ZERO_STRUCTP( data );
3649 return WERR_OK;
3652 /****************************************************************************
3653 ***************************************************************************/
3655 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3657 WERROR result = WERR_OK;
3658 int key_index;
3660 /* we must have names on non-zero length */
3662 if ( !key || !*key|| !value || !*value )
3663 return WERR_INVALID_NAME;
3665 /* find the printer key first */
3667 key_index = lookup_printerkey( p2->data, key );
3668 if ( key_index == -1 )
3669 return WERR_OK;
3671 /* make sure the value exists so we can return the correct error code */
3673 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3674 return WERR_BADFILE;
3676 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3678 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3679 key, value ));
3681 return result;
3684 /****************************************************************************
3685 ***************************************************************************/
3687 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3688 uint32 type, uint8 *data, int real_len )
3690 WERROR result = WERR_OK;
3691 int key_index;
3693 /* we must have names on non-zero length */
3695 if ( !key || !*key|| !value || !*value )
3696 return WERR_INVALID_NAME;
3698 /* find the printer key first */
3700 key_index = lookup_printerkey( p2->data, key );
3701 if ( key_index == -1 )
3702 key_index = add_new_printer_key( p2->data, key );
3704 if ( key_index == -1 )
3705 return WERR_NOMEM;
3707 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3708 type, data, real_len );
3710 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3711 key, value, type, real_len ));
3713 return result;
3716 /****************************************************************************
3717 ***************************************************************************/
3719 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3721 int key_index;
3723 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3724 return NULL;
3726 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3727 key, value ));
3729 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3732 /****************************************************************************
3733 Unpack a list of registry values frem the TDB
3734 ***************************************************************************/
3736 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3738 int len = 0;
3739 uint32 type;
3740 fstring string;
3741 const char *valuename = NULL;
3742 const char *keyname = NULL;
3743 char *str;
3744 int size;
3745 uint8 *data_p;
3746 struct regval_blob *regval_p;
3747 int key_index;
3749 /* add the "PrinterDriverData" key first for performance reasons */
3751 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3753 /* loop and unpack the rest of the registry values */
3755 while ( True ) {
3757 /* check to see if there are any more registry values */
3759 regval_p = NULL;
3760 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3761 if ( !regval_p )
3762 break;
3764 /* unpack the next regval */
3766 len += tdb_unpack(buf+len, buflen-len, "fdB",
3767 string,
3768 &type,
3769 &size,
3770 &data_p);
3772 /* lookup for subkey names which have a type of REG_NONE */
3773 /* there's no data with this entry */
3775 if ( type == REG_NONE ) {
3776 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3777 add_new_printer_key( printer_data, string );
3778 continue;
3782 * break of the keyname from the value name.
3783 * Valuenames can have embedded '\'s so be careful.
3784 * only support one level of keys. See the
3785 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3786 * -- jerry
3789 str = strchr_m( string, '\\');
3791 /* Put in "PrinterDriverData" is no key specified */
3793 if ( !str ) {
3794 keyname = SPOOL_PRINTERDATA_KEY;
3795 valuename = string;
3797 else {
3798 *str = '\0';
3799 keyname = string;
3800 valuename = str+1;
3803 /* see if we need a new key */
3805 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3806 key_index = add_new_printer_key( printer_data, keyname );
3808 if ( key_index == -1 ) {
3809 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3810 keyname));
3811 break;
3814 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3816 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3817 Thanks to Martin Zielinski for the hint. */
3819 if ( type == REG_BINARY &&
3820 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3821 strequal( valuename, "objectGUID" ) )
3823 struct GUID guid;
3825 /* convert the GUID to a UNICODE string */
3827 memcpy( &guid, data_p, sizeof(struct GUID) );
3829 regval_ctr_addvalue_sz(printer_data->keys[key_index].values,
3830 valuename,
3831 GUID_string(talloc_tos(), &guid));
3833 } else {
3834 /* add the value */
3836 regval_ctr_addvalue( printer_data->keys[key_index].values,
3837 valuename, type, data_p,
3838 size );
3841 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3845 return len;
3848 /****************************************************************************
3849 ***************************************************************************/
3851 static char *win_driver;
3852 static char *os2_driver;
3854 static const char *get_win_driver(void)
3856 if (win_driver == NULL) {
3857 return "";
3859 return win_driver;
3862 static const char *get_os2_driver(void)
3864 if (os2_driver == NULL) {
3865 return "";
3867 return os2_driver;
3870 static bool set_driver_mapping(const char *from, const char *to)
3872 SAFE_FREE(win_driver);
3873 SAFE_FREE(os2_driver);
3875 win_driver = SMB_STRDUP(from);
3876 os2_driver = SMB_STRDUP(to);
3878 if (win_driver == NULL || os2_driver == NULL) {
3879 SAFE_FREE(win_driver);
3880 SAFE_FREE(os2_driver);
3881 return false;
3883 return true;
3886 static void map_to_os2_driver(fstring drivername)
3888 char *mapfile = lp_os2_driver_map();
3889 char **lines = NULL;
3890 int numlines = 0;
3891 int i;
3893 if (!strlen(drivername))
3894 return;
3896 if (!*mapfile)
3897 return;
3899 if (strequal(drivername, get_win_driver())) {
3900 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3901 drivername, get_os2_driver()));
3902 fstrcpy(drivername, get_os2_driver());
3903 return;
3906 lines = file_lines_load(mapfile, &numlines,0,NULL);
3907 if (numlines == 0 || lines == NULL) {
3908 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3909 TALLOC_FREE(lines);
3910 return;
3913 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3915 for( i = 0; i < numlines; i++) {
3916 char *nt_name = lines[i];
3917 char *os2_name = strchr(nt_name,'=');
3919 if (!os2_name)
3920 continue;
3922 *os2_name++ = 0;
3924 while (isspace(*nt_name))
3925 nt_name++;
3927 if (!*nt_name || strchr("#;",*nt_name))
3928 continue;
3931 int l = strlen(nt_name);
3932 while (l && isspace(nt_name[l-1])) {
3933 nt_name[l-1] = 0;
3934 l--;
3938 while (isspace(*os2_name))
3939 os2_name++;
3942 int l = strlen(os2_name);
3943 while (l && isspace(os2_name[l-1])) {
3944 os2_name[l-1] = 0;
3945 l--;
3949 if (strequal(nt_name,drivername)) {
3950 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3951 set_driver_mapping(drivername,os2_name);
3952 fstrcpy(drivername,os2_name);
3953 TALLOC_FREE(lines);
3954 return;
3958 TALLOC_FREE(lines);
3962 * @internal
3964 * @brief Map a Windows driver to a OS/2 driver.
3966 * @param[in] mem_ctx The memory context to use.
3968 * @param[in,out] pdrivername The drivername of Windows to remap.
3970 * @return WERR_OK on success, a corresponding WERROR on failure.
3972 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
3974 const char *mapfile = lp_os2_driver_map();
3975 char **lines = NULL;
3976 const char *drivername;
3977 int numlines = 0;
3978 int i;
3980 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
3981 return WERR_INVALID_PARAMETER;
3984 drivername = *pdrivername;
3986 if (mapfile[0] == '\0') {
3987 return WERR_BADFILE;
3990 if (strequal(drivername, get_win_driver())) {
3991 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3992 drivername, get_os2_driver()));
3993 drivername = talloc_strdup(mem_ctx, get_os2_driver());
3994 if (drivername == NULL) {
3995 return WERR_NOMEM;
3997 *pdrivername = drivername;
3998 return WERR_OK;
4001 lines = file_lines_load(mapfile, &numlines, 0, NULL);
4002 if (numlines == 0 || lines == NULL) {
4003 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
4004 TALLOC_FREE(lines);
4005 return WERR_EMPTY;
4008 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
4010 for( i = 0; i < numlines; i++) {
4011 char *nt_name = lines[i];
4012 char *os2_name = strchr(nt_name, '=');
4014 if (os2_name == NULL) {
4015 continue;
4018 *os2_name++ = '\0';
4020 while (isspace(*nt_name)) {
4021 nt_name++;
4024 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
4025 continue;
4029 int l = strlen(nt_name);
4030 while (l && isspace(nt_name[l - 1])) {
4031 nt_name[l - 1] = 0;
4032 l--;
4036 while (isspace(*os2_name)) {
4037 os2_name++;
4041 int l = strlen(os2_name);
4042 while (l && isspace(os2_name[l-1])) {
4043 os2_name[l-1] = 0;
4044 l--;
4048 if (strequal(nt_name, drivername)) {
4049 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
4050 set_driver_mapping(drivername, os2_name);
4051 drivername = talloc_strdup(mem_ctx, os2_name);
4052 TALLOC_FREE(lines);
4053 if (drivername == NULL) {
4054 return WERR_NOMEM;
4056 *pdrivername = drivername;
4057 return WERR_OK;
4061 TALLOC_FREE(lines);
4062 return WERR_OK;
4065 /****************************************************************************
4066 Get a default printer info 2 struct.
4067 ****************************************************************************/
4069 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
4070 const char *servername,
4071 const char* sharename,
4072 bool get_loc_com)
4074 int snum = lp_servicenumber(sharename);
4076 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4077 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4078 servername, sharename);
4079 fstrcpy(info->sharename, sharename);
4080 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
4082 /* by setting the driver name to an empty string, a local NT admin
4083 can now run the **local** APW to install a local printer driver
4084 for a Samba shared printer in 2.2. Without this, drivers **must** be
4085 installed on the Samba server for NT clients --jerry */
4086 #if 0 /* JERRY --do not uncomment-- */
4087 if (!*info->drivername)
4088 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
4089 #endif
4092 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
4094 strlcpy(info->comment, "", sizeof(info->comment));
4095 fstrcpy(info->printprocessor, "winprint");
4096 fstrcpy(info->datatype, "RAW");
4098 #ifdef HAVE_CUPS
4099 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4100 /* Pull the location and comment strings from cups if we don't
4101 already have one */
4102 if ( !strlen(info->location) || !strlen(info->comment) ) {
4103 char *comment = NULL;
4104 char *location = NULL;
4105 if (cups_pull_comment_location(info, info->sharename,
4106 &comment, &location)) {
4107 strlcpy(info->comment, comment, sizeof(info->comment));
4108 fstrcpy(info->location, location);
4109 TALLOC_FREE(comment);
4110 TALLOC_FREE(location);
4114 #endif
4116 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
4118 info->starttime = 0; /* Minutes since 12:00am GMT */
4119 info->untiltime = 0; /* Minutes since 12:00am GMT */
4120 info->priority = 1;
4121 info->default_priority = 1;
4122 info->setuptime = (uint32)time(NULL);
4125 * I changed this as I think it is better to have a generic
4126 * DEVMODE than to crash Win2k explorer.exe --jerry
4127 * See the HP Deskjet 990c Win2k drivers for an example.
4129 * However the default devmode appears to cause problems
4130 * with the HP CLJ 8500 PCL driver. Hence the addition of
4131 * the "default devmode" parameter --jerry 22/01/2002
4134 if (lp_default_devmode(snum)) {
4135 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
4136 goto fail;
4138 } else {
4139 info->devmode = NULL;
4142 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4143 goto fail;
4146 info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
4147 if (!info->data) {
4148 goto fail;
4151 add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
4153 return WERR_OK;
4155 fail:
4156 if (info->devmode)
4157 free_nt_devicemode(&info->devmode);
4159 return WERR_ACCESS_DENIED;
4162 /****************************************************************************
4163 ****************************************************************************/
4165 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
4166 const char *servername,
4167 const char *sharename,
4168 bool get_loc_com)
4170 int len = 0;
4171 int snum = lp_servicenumber(sharename);
4172 TDB_DATA kbuf, dbuf;
4173 fstring printername;
4174 char adevice[MAXDEVICENAME];
4175 char *comment = NULL;
4177 kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4179 dbuf = tdb_fetch(tdb_printers, kbuf);
4180 if (!dbuf.dptr) {
4181 return get_a_printer_2_default(info, servername,
4182 sharename, get_loc_com);
4185 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4186 &info->attributes,
4187 &info->priority,
4188 &info->default_priority,
4189 &info->starttime,
4190 &info->untiltime,
4191 &info->status,
4192 &info->cjobs,
4193 &info->averageppm,
4194 &info->changeid,
4195 &info->c_setprinter,
4196 &info->setuptime,
4197 info->servername,
4198 info->printername,
4199 info->sharename,
4200 info->portname,
4201 info->drivername,
4202 &comment,
4203 info->location,
4204 info->sepfile,
4205 info->printprocessor,
4206 info->datatype,
4207 info->parameters);
4209 if (comment) {
4210 strlcpy(info->comment, comment, sizeof(info->comment));
4211 SAFE_FREE(comment);
4214 /* Samba has to have shared raw drivers. */
4215 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4216 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4218 /* Restore the stripped strings. */
4219 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4221 if ( lp_force_printername(snum) ) {
4222 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4223 } else {
4224 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4227 fstrcpy(info->printername, printername);
4229 #ifdef HAVE_CUPS
4230 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4231 /* Pull the location and comment strings from cups if we don't
4232 already have one */
4233 if ( !strlen(info->location) || !strlen(info->comment) ) {
4234 char *location = NULL;
4235 comment = NULL;
4236 if (cups_pull_comment_location(info, info->sharename,
4237 &comment, &location)) {
4238 strlcpy(info->comment, comment, sizeof(info->comment));
4239 fstrcpy(info->location, location);
4240 TALLOC_FREE(comment);
4241 TALLOC_FREE(location);
4245 #endif
4247 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4250 * Some client drivers freak out if there is a NULL devmode
4251 * (probably the driver is not checking before accessing
4252 * the devmode pointer) --jerry
4254 * See comments in get_a_printer_2_default()
4257 if (lp_default_devmode(snum) && !info->devmode) {
4258 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4259 printername));
4260 info->devmode = construct_nt_devicemode(printername);
4263 slprintf( adevice, sizeof(adevice), "%s", info->printername );
4264 if (info->devmode) {
4265 fstrcpy(info->devmode->devicename, adevice);
4268 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4269 DEBUG(0,("unpack_values: talloc() failed!\n"));
4270 SAFE_FREE(dbuf.dptr);
4271 return WERR_NOMEM;
4273 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4275 /* This will get the current RPC talloc context, but we should be
4276 passing this as a parameter... fixme... JRA ! */
4278 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4279 SAFE_FREE(dbuf.dptr);
4280 return WERR_NOMEM;
4283 /* Fix for OS/2 drivers. */
4285 if (get_remote_arch() == RA_OS2) {
4286 map_to_os2_driver(info->drivername);
4289 SAFE_FREE(dbuf.dptr);
4291 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4292 sharename, info->printername, info->drivername));
4294 return WERR_OK;
4297 /****************************************************************************
4298 Debugging function, dump at level 6 the struct in the logs.
4299 ****************************************************************************/
4300 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4302 uint32 result;
4303 NT_PRINTER_INFO_LEVEL_2 *info2;
4305 DEBUG(106,("Dumping printer at level [%d]\n", level));
4307 switch (level) {
4308 case 2:
4310 if (printer->info_2 == NULL)
4311 result=5;
4312 else
4314 info2=printer->info_2;
4316 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4317 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4318 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4319 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4320 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4321 DEBUGADD(106,("status:[%d]\n", info2->status));
4322 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4323 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4324 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4325 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4326 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4328 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4329 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4330 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4331 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4332 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4333 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4334 DEBUGADD(106,("location:[%s]\n", info2->location));
4335 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4336 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4337 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4338 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4339 result=0;
4341 break;
4343 default:
4344 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4345 result=1;
4346 break;
4349 return result;
4352 /****************************************************************************
4353 Update the changeid time.
4354 This is SO NASTY as some drivers need this to change, others need it
4355 static. This value will change every second, and I must hope that this
4356 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4357 UTAH ! JRA.
4358 ****************************************************************************/
4360 static uint32 rev_changeid(void)
4362 struct timeval tv;
4364 get_process_uptime(&tv);
4366 #if 1 /* JERRY */
4367 /* Return changeid as msec since spooler restart */
4368 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4369 #else
4371 * This setting seems to work well but is too untested
4372 * to replace the above calculation. Left in for experiementation
4373 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4375 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4376 #endif
4381 * The function below are the high level ones.
4382 * only those ones must be called from the spoolss code.
4383 * JFM.
4386 /****************************************************************************
4387 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4388 ****************************************************************************/
4390 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4392 WERROR result;
4394 dump_a_printer(printer, level);
4396 switch (level) {
4397 case 2:
4400 * Update the changestamp. Emperical tests show that the
4401 * ChangeID is always updated,but c_setprinter is
4402 * global spooler variable (not per printer).
4405 /* ChangeID **must** be increasing over the lifetime
4406 of client's spoolss service in order for the
4407 client's cache to show updates */
4409 printer->info_2->changeid = rev_changeid();
4412 * Because one day someone will ask:
4413 * NT->NT An admin connection to a remote
4414 * printer show changes imeediately in
4415 * the properities dialog
4417 * A non-admin connection will only show the
4418 * changes after viewing the properites page
4419 * 2 times. Seems to be related to a
4420 * race condition in the client between the spooler
4421 * updating the local cache and the Explorer.exe GUI
4422 * actually displaying the properties.
4424 * This is fixed in Win2k. admin/non-admin
4425 * connections both display changes immediately.
4427 * 14/12/01 --jerry
4430 result=update_a_printer_2(printer->info_2);
4431 break;
4433 default:
4434 result=WERR_UNKNOWN_LEVEL;
4435 break;
4438 return result;
4441 /****************************************************************************
4442 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4444 Previously the code had a memory allocation problem because it always
4445 used the TALLOC_CTX from the Printer_entry*. This context lasts
4446 as a long as the original handle is open. So if the client made a lot
4447 of getprinter[data]() calls, the memory usage would climb. Now we use
4448 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4449 still use the Printer_entry->ctx for maintaining the cache copy though
4450 since that object must live as long as the handle by definition.
4451 --jerry
4453 ****************************************************************************/
4455 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4456 const char *sharename, bool get_loc_com)
4458 WERROR result;
4459 fstring servername;
4461 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4463 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4464 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4465 return WERR_NOMEM;
4468 switch (level) {
4469 case 2:
4470 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4471 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4472 TALLOC_FREE( *pp_printer );
4473 return WERR_NOMEM;
4476 if ( print_hnd )
4477 fstrcpy( servername, print_hnd->servername );
4478 else {
4479 fstrcpy( servername, "%L" );
4480 standard_sub_basic( "", "", servername,
4481 sizeof(servername)-1 );
4484 result = get_a_printer_2( (*pp_printer)->info_2,
4485 servername, sharename, get_loc_com);
4487 /* we have a new printer now. Save it with this handle */
4489 if ( !W_ERROR_IS_OK(result) ) {
4490 TALLOC_FREE( *pp_printer );
4491 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4492 sharename, (unsigned int)level, win_errstr(result)));
4493 return result;
4496 dump_a_printer( *pp_printer, level);
4498 break;
4500 default:
4501 TALLOC_FREE( *pp_printer );
4502 return WERR_UNKNOWN_LEVEL;
4505 return WERR_OK;
4508 WERROR get_a_printer( Printer_entry *print_hnd,
4509 NT_PRINTER_INFO_LEVEL **pp_printer,
4510 uint32 level,
4511 const char *sharename)
4513 return get_a_printer_internal(print_hnd, pp_printer, level,
4514 sharename, true);
4517 WERROR get_a_printer_search( Printer_entry *print_hnd,
4518 NT_PRINTER_INFO_LEVEL **pp_printer,
4519 uint32 level,
4520 const char *sharename)
4522 return get_a_printer_internal(print_hnd, pp_printer, level,
4523 sharename, false);
4526 /****************************************************************************
4527 Deletes a NT_PRINTER_INFO_LEVEL struct.
4528 ****************************************************************************/
4530 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4532 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4534 if ( !printer )
4535 return 0;
4537 switch (level) {
4538 case 2:
4539 if ( printer->info_2 )
4540 free_nt_printer_info_level_2(&printer->info_2);
4541 break;
4543 default:
4544 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4545 return 1;
4548 TALLOC_FREE(*pp_printer);
4550 return 0;
4553 /****************************************************************************
4554 ****************************************************************************/
4556 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
4557 struct spoolss_DriverInfo8 *_info8)
4559 struct spoolss_DriverInfo8 info8;
4561 ZERO_STRUCT(info8);
4563 switch (r->level) {
4564 case 3:
4565 info8.version = r->info.info3->version;
4566 info8.driver_name = r->info.info3->driver_name;
4567 info8.architecture = r->info.info3->architecture;
4568 info8.driver_path = r->info.info3->driver_path;
4569 info8.data_file = r->info.info3->data_file;
4570 info8.config_file = r->info.info3->config_file;
4571 info8.help_file = r->info.info3->help_file;
4572 info8.monitor_name = r->info.info3->monitor_name;
4573 info8.default_datatype = r->info.info3->default_datatype;
4574 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
4575 info8.dependent_files = r->info.info3->dependent_files->string;
4577 break;
4578 case 6:
4579 info8.version = r->info.info6->version;
4580 info8.driver_name = r->info.info6->driver_name;
4581 info8.architecture = r->info.info6->architecture;
4582 info8.driver_path = r->info.info6->driver_path;
4583 info8.data_file = r->info.info6->data_file;
4584 info8.config_file = r->info.info6->config_file;
4585 info8.help_file = r->info.info6->help_file;
4586 info8.monitor_name = r->info.info6->monitor_name;
4587 info8.default_datatype = r->info.info6->default_datatype;
4588 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
4589 info8.dependent_files = r->info.info6->dependent_files->string;
4591 info8.driver_date = r->info.info6->driver_date;
4592 info8.driver_version = r->info.info6->driver_version;
4593 info8.manufacturer_name = r->info.info6->manufacturer_name;
4594 info8.manufacturer_url = r->info.info6->manufacturer_url;
4595 info8.hardware_id = r->info.info6->hardware_id;
4596 info8.provider = r->info.info6->provider;
4597 break;
4598 case 8:
4599 info8.version = r->info.info8->version;
4600 info8.driver_name = r->info.info8->driver_name;
4601 info8.architecture = r->info.info8->architecture;
4602 info8.driver_path = r->info.info8->driver_path;
4603 info8.data_file = r->info.info8->data_file;
4604 info8.config_file = r->info.info8->config_file;
4605 info8.help_file = r->info.info8->help_file;
4606 info8.monitor_name = r->info.info8->monitor_name;
4607 info8.default_datatype = r->info.info8->default_datatype;
4608 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
4609 info8.dependent_files = r->info.info8->dependent_files->string;
4611 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
4612 info8.previous_names = r->info.info8->previous_names->string;
4614 info8.driver_date = r->info.info8->driver_date;
4615 info8.driver_version = r->info.info8->driver_version;
4616 info8.manufacturer_name = r->info.info8->manufacturer_name;
4617 info8.manufacturer_url = r->info.info8->manufacturer_url;
4618 info8.hardware_id = r->info.info8->hardware_id;
4619 info8.provider = r->info.info8->provider;
4620 info8.print_processor = r->info.info8->print_processor;
4621 info8.vendor_setup = r->info.info8->vendor_setup;
4622 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
4623 info8.color_profiles = r->info.info8->color_profiles->string;
4625 info8.inf_path = r->info.info8->inf_path;
4626 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
4627 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
4628 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
4630 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
4631 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
4632 break;
4633 default:
4634 return false;
4637 *_info8 = info8;
4639 return true;
4643 uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx,
4644 struct spoolss_AddDriverInfoCtr *r,
4645 char **driver_name,
4646 uint32_t *version)
4648 struct spoolss_DriverInfo8 info8;
4650 ZERO_STRUCT(info8);
4652 DEBUG(10,("adding a printer at level [%d]\n", r->level));
4654 if (!driver_info_ctr_to_info8(r, &info8)) {
4655 return -1;
4658 *driver_name = talloc_strdup(mem_ctx, info8.driver_name);
4659 if (!*driver_name) {
4660 return -1;
4662 *version = info8.version;
4664 return add_a_printer_driver_8(&info8);
4667 /****************************************************************************
4668 ****************************************************************************/
4670 WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx,
4671 struct spoolss_DriverInfo8 **driver,
4672 const char *drivername, const char *architecture,
4673 uint32_t version)
4675 WERROR result;
4676 struct spoolss_DriverInfo3 info3;
4677 struct spoolss_DriverInfo8 *info8;
4679 ZERO_STRUCT(info3);
4681 /* Sometime we just want any version of the driver */
4683 if (version == DRIVER_ANY_VERSION) {
4684 /* look for Win2k first and then for NT4 */
4685 result = get_a_printer_driver_3(mem_ctx,
4686 &info3,
4687 drivername,
4688 architecture, 3);
4689 if (!W_ERROR_IS_OK(result)) {
4690 result = get_a_printer_driver_3(mem_ctx,
4691 &info3,
4692 drivername,
4693 architecture, 2);
4695 } else {
4696 result = get_a_printer_driver_3(mem_ctx,
4697 &info3,
4698 drivername,
4699 architecture,
4700 version);
4703 if (!W_ERROR_IS_OK(result)) {
4704 return result;
4707 info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8);
4708 if (!info8) {
4709 return WERR_NOMEM;
4712 info8->version = info3.version;
4713 info8->driver_name = info3.driver_name;
4714 info8->architecture = info3.architecture;
4715 info8->driver_path = info3.driver_path;
4716 info8->data_file = info3.data_file;
4717 info8->config_file = info3.config_file;
4718 info8->help_file = info3.help_file;
4719 info8->dependent_files = info3.dependent_files;
4720 info8->monitor_name = info3.monitor_name;
4721 info8->default_datatype = info3.default_datatype;
4723 *driver = info8;
4725 return WERR_OK;
4728 /****************************************************************************
4729 ****************************************************************************/
4731 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver)
4733 talloc_free(driver);
4734 return 0;
4738 /****************************************************************************
4739 Determine whether or not a particular driver is currently assigned
4740 to a printer
4741 ****************************************************************************/
4743 bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r)
4745 int snum;
4746 int n_services = lp_numservices();
4747 NT_PRINTER_INFO_LEVEL *printer = NULL;
4748 bool in_use = False;
4750 if (!r) {
4751 return false;
4754 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4756 /* loop through the printers.tdb and check for the drivername */
4758 for (snum=0; snum<n_services && !in_use; snum++) {
4759 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4760 continue;
4762 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4763 continue;
4765 if (strequal(r->driver_name, printer->info_2->drivername))
4766 in_use = True;
4768 free_a_printer( &printer, 2 );
4771 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4773 if ( in_use ) {
4774 struct spoolss_DriverInfo8 *d;
4775 WERROR werr;
4777 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
4779 /* we can still remove the driver if there is one of
4780 "Windows NT x86" version 2 or 3 left */
4782 if (!strequal("Windows NT x86", r->architecture)) {
4783 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION);
4785 else {
4786 switch (r->version) {
4787 case 2:
4788 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3);
4789 break;
4790 case 3:
4791 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2);
4792 break;
4793 default:
4794 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4795 r->version));
4796 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4797 break;
4801 /* now check the error code */
4803 if ( W_ERROR_IS_OK(werr) ) {
4804 /* it's ok to remove the driver, we have other architctures left */
4805 in_use = False;
4806 free_a_printer_driver(d);
4810 /* report that the driver is not in use by default */
4812 return in_use;
4816 /**********************************************************************
4817 Check to see if a ogiven file is in use by *info
4818 *********************************************************************/
4820 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
4822 int i = 0;
4824 if ( !info )
4825 return False;
4827 /* mz: skip files that are in the list but already deleted */
4828 if (!file || !file[0]) {
4829 return false;
4832 if (strequal(file, info->driver_path))
4833 return True;
4835 if (strequal(file, info->data_file))
4836 return True;
4838 if (strequal(file, info->config_file))
4839 return True;
4841 if (strequal(file, info->help_file))
4842 return True;
4844 /* see of there are any dependent files to examine */
4846 if (!info->dependent_files)
4847 return False;
4849 while (info->dependent_files[i] && *info->dependent_files[i]) {
4850 if (strequal(file, info->dependent_files[i]))
4851 return True;
4852 i++;
4855 return False;
4859 /**********************************************************************
4860 Utility function to remove the dependent file pointed to by the
4861 input parameter from the list
4862 *********************************************************************/
4864 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
4867 /* bump everything down a slot */
4869 while (files && files[idx+1]) {
4870 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
4871 idx++;
4874 files[idx] = NULL;
4876 return;
4879 /**********************************************************************
4880 Check if any of the files used by src are also used by drv
4881 *********************************************************************/
4883 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
4884 struct spoolss_DriverInfo8 *src,
4885 const struct spoolss_DriverInfo8 *drv)
4887 bool in_use = False;
4888 int i = 0;
4890 if ( !src || !drv )
4891 return False;
4893 /* check each file. Remove it from the src structure if it overlaps */
4895 if (drv_file_in_use(src->driver_path, drv)) {
4896 in_use = True;
4897 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
4898 src->driver_path = talloc_strdup(mem_ctx, "");
4899 if (!src->driver_path) { return false; }
4902 if (drv_file_in_use(src->data_file, drv)) {
4903 in_use = True;
4904 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
4905 src->data_file = talloc_strdup(mem_ctx, "");
4906 if (!src->data_file) { return false; }
4909 if (drv_file_in_use(src->config_file, drv)) {
4910 in_use = True;
4911 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
4912 src->config_file = talloc_strdup(mem_ctx, "");
4913 if (!src->config_file) { return false; }
4916 if (drv_file_in_use(src->help_file, drv)) {
4917 in_use = True;
4918 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
4919 src->help_file = talloc_strdup(mem_ctx, "");
4920 if (!src->help_file) { return false; }
4923 /* are there any dependentfiles to examine? */
4925 if (!src->dependent_files)
4926 return in_use;
4928 while (src->dependent_files[i] && *src->dependent_files[i]) {
4929 if (drv_file_in_use(src->dependent_files[i], drv)) {
4930 in_use = True;
4931 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
4932 trim_dependent_file(mem_ctx, src->dependent_files, i);
4933 } else
4934 i++;
4937 return in_use;
4940 /****************************************************************************
4941 Determine whether or not a particular driver files are currently being
4942 used by any other driver.
4944 Return value is True if any files were in use by other drivers
4945 and False otherwise.
4947 Upon return, *info has been modified to only contain the driver files
4948 which are not in use
4950 Fix from mz:
4952 This needs to check all drivers to ensure that all files in use
4953 have been removed from *info, not just the ones in the first
4954 match.
4955 ****************************************************************************/
4957 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
4958 struct spoolss_DriverInfo8 *info)
4960 int i;
4961 int ndrivers;
4962 uint32 version;
4963 fstring *list = NULL;
4964 struct spoolss_DriverInfo8 *driver;
4965 bool in_use = false;
4967 if ( !info )
4968 return False;
4970 version = info->version;
4972 /* loop over all driver versions */
4974 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4976 /* get the list of drivers */
4978 list = NULL;
4979 ndrivers = get_ntdrivers(&list, info->architecture, version);
4981 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4982 ndrivers, info->architecture, version));
4984 /* check each driver for overlap in files */
4986 for (i=0; i<ndrivers; i++) {
4987 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4989 driver = NULL;
4991 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, list[i], info->architecture, version))) {
4992 SAFE_FREE(list);
4993 return True;
4996 /* check if d2 uses any files from d1 */
4997 /* only if this is a different driver than the one being deleted */
4999 if (!strequal(info->driver_name, driver->driver_name)) {
5000 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
5001 /* mz: Do not instantly return -
5002 * we need to ensure this file isn't
5003 * also in use by other drivers. */
5004 in_use = true;
5008 free_a_printer_driver(driver);
5011 SAFE_FREE(list);
5013 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5015 return in_use;
5018 static NTSTATUS driver_unlink_internals(connection_struct *conn,
5019 const char *name)
5021 struct smb_filename *smb_fname = NULL;
5022 NTSTATUS status;
5024 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
5025 &smb_fname);
5026 if (!NT_STATUS_IS_OK(status)) {
5027 return status;
5030 status = unlink_internals(conn, NULL, 0, smb_fname, false);
5032 TALLOC_FREE(smb_fname);
5033 return status;
5036 /****************************************************************************
5037 Actually delete the driver files. Make sure that
5038 printer_driver_files_in_use() return False before calling
5039 this.
5040 ****************************************************************************/
5042 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
5043 const struct spoolss_DriverInfo8 *r)
5045 int i = 0;
5046 char *s;
5047 const char *file;
5048 connection_struct *conn;
5049 NTSTATUS nt_status;
5050 char *oldcwd;
5051 fstring printdollar;
5052 int printdollar_snum;
5053 bool ret = false;
5055 if (!r) {
5056 return false;
5059 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
5060 r->driver_name, r->version));
5062 fstrcpy(printdollar, "print$");
5064 printdollar_snum = find_service(printdollar);
5065 if (printdollar_snum == -1) {
5066 return false;
5069 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5070 lp_pathname(printdollar_snum),
5071 rpc_pipe->server_info, &oldcwd);
5072 if (!NT_STATUS_IS_OK(nt_status)) {
5073 DEBUG(0,("delete_driver_files: create_conn_struct "
5074 "returned %s\n", nt_errstr(nt_status)));
5075 return false;
5078 if ( !CAN_WRITE(conn) ) {
5079 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5080 goto fail;
5083 /* now delete the files; must strip the '\print$' string from
5084 fron of path */
5086 if (r->driver_path && r->driver_path[0]) {
5087 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
5088 file = s;
5089 DEBUG(10,("deleting driverfile [%s]\n", s));
5090 driver_unlink_internals(conn, file);
5094 if (r->config_file && r->config_file[0]) {
5095 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
5096 file = s;
5097 DEBUG(10,("deleting configfile [%s]\n", s));
5098 driver_unlink_internals(conn, file);
5102 if (r->data_file && r->data_file[0]) {
5103 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
5104 file = s;
5105 DEBUG(10,("deleting datafile [%s]\n", s));
5106 driver_unlink_internals(conn, file);
5110 if (r->help_file && r->help_file[0]) {
5111 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
5112 file = s;
5113 DEBUG(10,("deleting helpfile [%s]\n", s));
5114 driver_unlink_internals(conn, file);
5118 /* check if we are done removing files */
5120 if (r->dependent_files) {
5121 while (r->dependent_files[i] && r->dependent_files[i][0]) {
5122 char *p;
5124 /* bypass the "\print$" portion of the path */
5126 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
5127 file = p;
5128 DEBUG(10,("deleting dependent file [%s]\n", file));
5129 driver_unlink_internals(conn, file);
5132 i++;
5136 goto done;
5137 fail:
5138 ret = false;
5139 done:
5140 if (conn != NULL) {
5141 vfs_ChDir(conn, oldcwd);
5142 conn_free(conn);
5144 return ret;
5147 /****************************************************************************
5148 Remove a printer driver from the TDB. This assumes that the the driver was
5149 previously looked up.
5150 ***************************************************************************/
5152 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5153 const struct spoolss_DriverInfo8 *r,
5154 uint32 version, bool delete_files )
5156 char *key = NULL;
5157 const char *arch;
5158 TDB_DATA dbuf;
5160 /* delete the tdb data first */
5162 arch = get_short_archi(r->architecture);
5163 if (!arch) {
5164 return WERR_UNKNOWN_PRINTER_DRIVER;
5166 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5167 arch, version, r->driver_name) < 0) {
5168 return WERR_NOMEM;
5171 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5172 key, delete_files ? "TRUE" : "FALSE" ));
5174 /* check if the driver actually exists for this environment */
5176 dbuf = tdb_fetch_bystring( tdb_drivers, key );
5177 if ( !dbuf.dptr ) {
5178 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5179 SAFE_FREE(key);
5180 return WERR_UNKNOWN_PRINTER_DRIVER;
5183 SAFE_FREE( dbuf.dptr );
5185 /* ok... the driver exists so the delete should return success */
5187 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5188 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5189 SAFE_FREE(key);
5190 return WERR_ACCESS_DENIED;
5194 * now delete any associated files if delete_files == True
5195 * even if this part failes, we return succes because the
5196 * driver doesn not exist any more
5199 if ( delete_files )
5200 delete_driver_files(rpc_pipe, r);
5202 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5203 SAFE_FREE(key);
5205 return WERR_OK;
5208 /****************************************************************************
5209 Store a security desc for a printer.
5210 ****************************************************************************/
5212 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
5214 struct sec_desc_buf *new_secdesc_ctr = NULL;
5215 struct sec_desc_buf *old_secdesc_ctr = NULL;
5216 TALLOC_CTX *mem_ctx = NULL;
5217 TDB_DATA kbuf;
5218 TDB_DATA dbuf;
5219 DATA_BLOB blob;
5220 WERROR status;
5221 NTSTATUS nt_status;
5223 mem_ctx = talloc_init("nt_printing_setsec");
5224 if (mem_ctx == NULL)
5225 return WERR_NOMEM;
5227 /* The old owner and group sids of the security descriptor are not
5228 present when new ACEs are added or removed by changing printer
5229 permissions through NT. If they are NULL in the new security
5230 descriptor then copy them over from the old one. */
5232 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5233 struct dom_sid *owner_sid, *group_sid;
5234 struct security_acl *dacl, *sacl;
5235 struct security_descriptor *psd = NULL;
5236 size_t size;
5238 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5239 status = WERR_NOMEM;
5240 goto out;
5243 /* Pick out correct owner and group sids */
5245 owner_sid = secdesc_ctr->sd->owner_sid ?
5246 secdesc_ctr->sd->owner_sid :
5247 old_secdesc_ctr->sd->owner_sid;
5249 group_sid = secdesc_ctr->sd->group_sid ?
5250 secdesc_ctr->sd->group_sid :
5251 old_secdesc_ctr->sd->group_sid;
5253 dacl = secdesc_ctr->sd->dacl ?
5254 secdesc_ctr->sd->dacl :
5255 old_secdesc_ctr->sd->dacl;
5257 sacl = secdesc_ctr->sd->sacl ?
5258 secdesc_ctr->sd->sacl :
5259 old_secdesc_ctr->sd->sacl;
5261 /* Make a deep copy of the security descriptor */
5263 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5264 owner_sid, group_sid,
5265 sacl,
5266 dacl,
5267 &size);
5269 if (!psd) {
5270 status = WERR_NOMEM;
5271 goto out;
5274 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5277 if (!new_secdesc_ctr) {
5278 new_secdesc_ctr = secdesc_ctr;
5281 /* Store the security descriptor in a tdb */
5283 nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5284 &blob.data, &blob.length);
5285 if (!NT_STATUS_IS_OK(nt_status)) {
5286 status = ntstatus_to_werror(nt_status);
5287 goto out;
5290 kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5292 dbuf.dptr = (unsigned char *)blob.data;
5293 dbuf.dsize = blob.length;
5295 if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5296 status = WERR_OK;
5297 } else {
5298 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5299 status = WERR_BADFUNC;
5302 /* Free malloc'ed memory */
5303 talloc_free(blob.data);
5305 out:
5307 if (mem_ctx)
5308 talloc_destroy(mem_ctx);
5309 return status;
5312 /****************************************************************************
5313 Construct a default security descriptor buffer for a printer.
5314 ****************************************************************************/
5316 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
5318 struct security_ace ace[5]; /* max number of ace entries */
5319 int i = 0;
5320 uint32_t sa;
5321 struct security_acl *psa = NULL;
5322 struct sec_desc_buf *sdb = NULL;
5323 struct security_descriptor *psd = NULL;
5324 struct dom_sid adm_sid;
5325 size_t sd_size;
5327 /* Create an ACE where Everyone is allowed to print */
5329 sa = PRINTER_ACE_PRINT;
5330 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5331 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5333 /* Add the domain admins group if we are a DC */
5335 if ( IS_DC ) {
5336 struct dom_sid domadmins_sid;
5338 sid_compose(&domadmins_sid, get_global_sam_sid(),
5339 DOMAIN_RID_ADMINS);
5341 sa = PRINTER_ACE_FULL_CONTROL;
5342 init_sec_ace(&ace[i++], &domadmins_sid,
5343 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5344 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5345 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5346 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5348 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5349 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
5351 sa = PRINTER_ACE_FULL_CONTROL;
5352 init_sec_ace(&ace[i++], &adm_sid,
5353 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5354 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5355 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5356 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5359 /* add BUILTIN\Administrators as FULL CONTROL */
5361 sa = PRINTER_ACE_FULL_CONTROL;
5362 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5363 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5364 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5365 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5366 SEC_ACE_TYPE_ACCESS_ALLOWED,
5367 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5369 /* Make the security descriptor owned by the BUILTIN\Administrators */
5371 /* The ACL revision number in rpc_secdesc.h differs from the one
5372 created by NT when setting ACE entries in printer
5373 descriptors. NT4 complains about the property being edited by a
5374 NT5 machine. */
5376 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5377 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
5378 &global_sid_Builtin_Administrators,
5379 &global_sid_Builtin_Administrators,
5380 NULL, psa, &sd_size);
5383 if (!psd) {
5384 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5385 return NULL;
5388 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5390 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5391 (unsigned int)sd_size));
5393 return sdb;
5396 /****************************************************************************
5397 Get a security desc for a printer.
5398 ****************************************************************************/
5400 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
5402 TDB_DATA kbuf;
5403 TDB_DATA dbuf;
5404 DATA_BLOB blob;
5405 char *temp;
5406 NTSTATUS status;
5408 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5409 sharename = temp + 1;
5412 /* Fetch security descriptor from tdb */
5414 kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5416 dbuf = tdb_fetch(tdb_printers, kbuf);
5417 if (dbuf.dptr) {
5419 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5420 secdesc_ctr);
5421 SAFE_FREE(dbuf.dptr);
5423 if (NT_STATUS_IS_OK(status)) {
5424 return true;
5428 *secdesc_ctr = construct_default_printer_sdb(ctx);
5429 if (!*secdesc_ctr) {
5430 return false;
5433 status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5434 &blob.data, &blob.length);
5435 if (NT_STATUS_IS_OK(status)) {
5436 dbuf.dptr = (unsigned char *)blob.data;
5437 dbuf.dsize = blob.length;
5438 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5439 talloc_free(blob.data);
5442 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5443 this security descriptor has been created when winbindd was
5444 down. Take ownership of security descriptor. */
5446 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5447 struct dom_sid owner_sid;
5449 /* Change sd owner to workgroup administrator */
5451 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5452 struct sec_desc_buf *new_secdesc_ctr = NULL;
5453 struct security_descriptor *psd = NULL;
5454 size_t size;
5456 /* Create new sd */
5458 sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
5460 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5461 &owner_sid,
5462 (*secdesc_ctr)->sd->group_sid,
5463 (*secdesc_ctr)->sd->sacl,
5464 (*secdesc_ctr)->sd->dacl,
5465 &size);
5467 if (!psd) {
5468 return False;
5471 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5472 if (!new_secdesc_ctr) {
5473 return False;
5476 /* Swap with other one */
5478 *secdesc_ctr = new_secdesc_ctr;
5480 /* Set it */
5482 nt_printing_setsec(sharename, *secdesc_ctr);
5486 if (DEBUGLEVEL >= 10) {
5487 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
5488 int i;
5490 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5491 sharename, the_acl->num_aces));
5493 for (i = 0; i < the_acl->num_aces; i++) {
5494 DEBUG(10, ("%s %d %d 0x%08x\n",
5495 sid_string_dbg(&the_acl->aces[i].trustee),
5496 the_acl->aces[i].type, the_acl->aces[i].flags,
5497 the_acl->aces[i].access_mask));
5501 return True;
5504 /* error code:
5505 0: everything OK
5506 1: level not implemented
5507 2: file doesn't exist
5508 3: can't allocate memory
5509 4: can't free memory
5510 5: non existant struct
5514 A printer and a printer driver are 2 different things.
5515 NT manages them separatelly, Samba does the same.
5516 Why ? Simply because it's easier and it makes sense !
5518 Now explanation: You have 3 printers behind your samba server,
5519 2 of them are the same make and model (laser A and B). But laser B
5520 has an 3000 sheet feeder and laser A doesn't such an option.
5521 Your third printer is an old dot-matrix model for the accounting :-).
5523 If the /usr/local/samba/lib directory (default dir), you will have
5524 5 files to describe all of this.
5526 3 files for the printers (1 by printer):
5527 NTprinter_laser A
5528 NTprinter_laser B
5529 NTprinter_accounting
5530 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5531 NTdriver_printer model X
5532 NTdriver_printer model Y
5534 jfm: I should use this comment for the text file to explain
5535 same thing for the forms BTW.
5536 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5540 /* Convert generic access rights to printer object specific access rights.
5541 It turns out that NT4 security descriptors use generic access rights and
5542 NT5 the object specific ones. */
5544 void map_printer_permissions(struct security_descriptor *sd)
5546 int i;
5548 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5549 se_map_generic(&sd->dacl->aces[i].access_mask,
5550 &printer_generic_mapping);
5554 void map_job_permissions(struct security_descriptor *sd)
5556 int i;
5558 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5559 se_map_generic(&sd->dacl->aces[i].access_mask,
5560 &job_generic_mapping);
5565 /****************************************************************************
5566 Check a user has permissions to perform the given operation. We use the
5567 permission constants defined in include/rpc_spoolss.h to check the various
5568 actions we perform when checking printer access.
5570 PRINTER_ACCESS_ADMINISTER:
5571 print_queue_pause, print_queue_resume, update_printer_sec,
5572 update_printer, spoolss_addprinterex_level_2,
5573 _spoolss_setprinterdata
5575 PRINTER_ACCESS_USE:
5576 print_job_start
5578 JOB_ACCESS_ADMINISTER:
5579 print_job_delete, print_job_pause, print_job_resume,
5580 print_queue_purge
5582 Try access control in the following order (for performance reasons):
5583 1) root and SE_PRINT_OPERATOR can do anything (easy check)
5584 2) check security descriptor (bit comparisons in memory)
5585 3) "printer admins" (may result in numerous calls to winbind)
5587 ****************************************************************************/
5588 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5589 int access_type)
5591 struct sec_desc_buf *secdesc = NULL;
5592 uint32 access_granted;
5593 NTSTATUS status;
5594 const char *pname;
5595 TALLOC_CTX *mem_ctx = NULL;
5596 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5598 /* If user is NULL then use the current_user structure */
5600 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5602 if (server_info->utok.uid == sec_initial_uid()
5603 || user_has_privileges(server_info->ptok, &se_printop ) ) {
5604 return True;
5607 /* Get printer name */
5609 pname = PRINTERNAME(snum);
5611 if (!pname || !*pname) {
5612 errno = EACCES;
5613 return False;
5616 /* Get printer security descriptor */
5618 if(!(mem_ctx = talloc_init("print_access_check"))) {
5619 errno = ENOMEM;
5620 return False;
5623 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5624 talloc_destroy(mem_ctx);
5625 errno = ENOMEM;
5626 return False;
5629 if (access_type == JOB_ACCESS_ADMINISTER) {
5630 struct sec_desc_buf *parent_secdesc = secdesc;
5632 /* Create a child security descriptor to check permissions
5633 against. This is because print jobs are child objects
5634 objects of a printer. */
5636 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5638 if (!NT_STATUS_IS_OK(status)) {
5639 talloc_destroy(mem_ctx);
5640 errno = map_errno_from_nt_status(status);
5641 return False;
5644 map_job_permissions(secdesc->sd);
5645 } else {
5646 map_printer_permissions(secdesc->sd);
5649 /* Check access */
5650 status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5651 &access_granted);
5653 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5655 /* see if we need to try the printer admin list */
5657 if (!NT_STATUS_IS_OK(status) &&
5658 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5659 NULL, NULL, server_info->ptok,
5660 lp_printer_admin(snum)))) {
5661 talloc_destroy(mem_ctx);
5662 return True;
5665 talloc_destroy(mem_ctx);
5667 if (!NT_STATUS_IS_OK(status)) {
5668 errno = EACCES;
5671 return NT_STATUS_IS_OK(status);
5674 /****************************************************************************
5675 Check the time parameters allow a print operation.
5676 *****************************************************************************/
5678 bool print_time_access_check(const char *servicename)
5680 NT_PRINTER_INFO_LEVEL *printer = NULL;
5681 bool ok = False;
5682 time_t now = time(NULL);
5683 struct tm *t;
5684 uint32 mins;
5686 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5687 return False;
5689 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5690 ok = True;
5692 t = gmtime(&now);
5693 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5695 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5696 ok = True;
5698 free_a_printer(&printer, 2);
5700 if (!ok)
5701 errno = EACCES;
5703 return ok;
5706 /****************************************************************************
5707 Fill in the servername sent in the _spoolss_open_printer_ex() call
5708 ****************************************************************************/
5710 char* get_server_name( Printer_entry *printer )
5712 return printer->servername;