s3-spoolss: Removed the Phantom DeviceMode.
[nivanova/samba-autobuild/.git] / source3 / printing / nt_printing.c
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.
7  *
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.
12  *
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.
17  *
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/>.
20  */
21
22 #include "includes.h"
23 #include "librpc/gen_ndr/messaging.h"
24 #include "printing/pcap.h"
25 #include "registry.h"
26
27 static TDB_CONTEXT *tdb_forms; /* used for forms files */
28 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29 static TDB_CONTEXT *tdb_printers; /* used for printers files */
30
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define PRINTERS_PREFIX "PRINTERS/"
34 #define SECDESC_PREFIX "SECDESC/"
35 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
36
37 #define NTDRIVERS_DATABASE_VERSION_1 1
38 #define NTDRIVERS_DATABASE_VERSION_2 2
39 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
40 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
41 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
42
43 /* Map generic permissions to printer object specific permissions */
44
45 const struct generic_mapping printer_generic_mapping = {
46         PRINTER_READ,
47         PRINTER_WRITE,
48         PRINTER_EXECUTE,
49         PRINTER_ALL_ACCESS
50 };
51
52 const struct standard_mapping printer_std_mapping = {
53         PRINTER_READ,
54         PRINTER_WRITE,
55         PRINTER_EXECUTE,
56         PRINTER_ALL_ACCESS
57 };
58
59 /* Map generic permissions to print server object specific permissions */
60
61 const struct generic_mapping printserver_generic_mapping = {
62         SERVER_READ,
63         SERVER_WRITE,
64         SERVER_EXECUTE,
65         SERVER_ALL_ACCESS
66 };
67
68 const struct generic_mapping printserver_std_mapping = {
69         SERVER_READ,
70         SERVER_WRITE,
71         SERVER_EXECUTE,
72         SERVER_ALL_ACCESS
73 };
74
75 /* Map generic permissions to job object specific permissions */
76
77 const struct generic_mapping job_generic_mapping = {
78         JOB_READ,
79         JOB_WRITE,
80         JOB_EXECUTE,
81         JOB_ALL_ACCESS
82 };
83
84 /* We need one default form to support our default printer. Msoft adds the
85 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
86 array index). Letter is always first, so (for the current code) additions
87 always put things in the correct order. */
88 static const nt_forms_struct default_forms[] = {
89         {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
90         {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
91         {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
92         {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
93         {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
94         {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
95         {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
96         {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
97         {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
98         {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
99         {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
100         {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
101         {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
102         {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
103         {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
104         {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
105         {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
106         {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
107         {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
108         {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
109         {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
110         {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
111         {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
112         {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
113         {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
114         {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
115         {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
116         {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
117         {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
118         {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
119         {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
120         {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
121         {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
122         {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
123         {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
124         {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
125         {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
126         {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
127         {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
128         {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
129         {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
130         {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
131         {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
132         {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
133         {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
134         {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
135         {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
136         {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
137         {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
138         {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
139         {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
140         {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
141         {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
142         {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
143         {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
144         {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
145         {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
146         {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
147         {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
148         {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
149         {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
150         {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
151         {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
152         {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
153         {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
154         {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
155         {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
156         {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
157         {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
158         {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
159         {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
160         {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
161         {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
162         {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
163         {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
164         {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
165         {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
166         {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
167         {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
168         {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
169         {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
170         {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
171         {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
172         {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
173         {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
174         {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
175         {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
176         {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
177         {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
178         {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
179         {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
180         {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
181         {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
182         {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
183         {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
184         {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
185         {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
186         {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
187         {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
188         {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
189         {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
190         {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
191         {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
192         {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
193         {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
194         {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
195         {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
196         {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
197         {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
198         {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
199         {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
200         {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
201         {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
202         {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
203         {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
204         {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
205         {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
206         {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
207 };
208
209 static const struct print_architecture_table_node archi_table[]= {
210
211         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
212         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
213         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
214         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
215         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
216         {"Windows IA64",         SPL_ARCH_IA64,         3 },
217         {"Windows x64",          SPL_ARCH_X64,          3 },
218         {NULL,                   "",            -1 }
219 };
220
221
222 /****************************************************************************
223  generate a new TDB_DATA key for storing a printer
224 ****************************************************************************/
225
226 static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
227 {
228         fstring share;
229         char *keystr = NULL;
230         TDB_DATA key;
231
232         fstrcpy(share, sharename);
233         strlower_m(share);
234
235         keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
236         key = string_term_tdb_data(keystr ? keystr : "");
237
238         return key;
239 }
240
241 /****************************************************************************
242  generate a new TDB_DATA key for storing a printer security descriptor
243 ****************************************************************************/
244
245 static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
246                                         const char* sharename  )
247 {
248         fstring share;
249         char *keystr = NULL;
250         TDB_DATA key;
251
252         fstrcpy(share, sharename );
253         strlower_m(share);
254
255         keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
256         key = string_term_tdb_data(keystr ? keystr : "");
257
258         return key;
259 }
260
261 /****************************************************************************
262 ****************************************************************************/
263
264 static bool upgrade_to_version_3(void)
265 {
266         TDB_DATA kbuf, newkey, dbuf;
267
268         DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
269
270         for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
271                         newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
272
273                 dbuf = tdb_fetch(tdb_drivers, kbuf);
274
275                 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
276                         DEBUG(0,("upgrade_to_version_3:moving form\n"));
277                         if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
278                                 SAFE_FREE(dbuf.dptr);
279                                 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
280                                 return False;
281                         }
282                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
283                                 SAFE_FREE(dbuf.dptr);
284                                 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
285                                 return False;
286                         }
287                 }
288
289                 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
290                         DEBUG(0,("upgrade_to_version_3:moving printer\n"));
291                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
292                                 SAFE_FREE(dbuf.dptr);
293                                 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
294                                 return False;
295                         }
296                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
297                                 SAFE_FREE(dbuf.dptr);
298                                 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
299                                 return False;
300                         }
301                 }
302
303                 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
304                         DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
305                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
306                                 SAFE_FREE(dbuf.dptr);
307                                 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
308                                 return False;
309                         }
310                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
311                                 SAFE_FREE(dbuf.dptr);
312                                 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
313                                 return False;
314                         }
315                 }
316
317                 SAFE_FREE(dbuf.dptr);
318         }
319
320         return True;
321 }
322
323 /*******************************************************************
324  Fix an issue with security descriptors.  Printer sec_desc must
325  use more than the generic bits that were previously used
326  in <= 3.0.14a.  They must also have a owner and group SID assigned.
327  Otherwise, any printers than have been migrated to a Windows
328  host using printmig.exe will not be accessible.
329 *******************************************************************/
330
331 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
332                             TDB_DATA data, void *state )
333 {
334         NTSTATUS status;
335         struct sec_desc_buf *sd_orig = NULL;
336         struct sec_desc_buf *sd_new, *sd_store;
337         struct security_descriptor *sec, *new_sec;
338         TALLOC_CTX *ctx = state;
339         int result, i;
340         uint32 sd_size;
341         size_t size_new_sec;
342
343         if (!data.dptr || data.dsize == 0) {
344                 return 0;
345         }
346
347         if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
348                 return 0;
349         }
350
351         /* upgrade the security descriptor */
352
353         status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
354         if (!NT_STATUS_IS_OK(status)) {
355                 /* delete bad entries */
356                 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si.  Deleting....\n",
357                         (const char *)key.dptr ));
358                 tdb_delete( tdb_printers, key );
359                 return 0;
360         }
361
362         if (!sd_orig) {
363                 return 0;
364         }
365         sec = sd_orig->sd;
366
367         /* is this even valid? */
368
369         if ( !sec->dacl ) {
370                 return 0;
371         }
372
373         /* update access masks */
374
375         for ( i=0; i<sec->dacl->num_aces; i++ ) {
376                 switch ( sec->dacl->aces[i].access_mask ) {
377                         case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
378                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
379                                 break;
380
381                         case GENERIC_ALL_ACCESS:
382                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
383                                 break;
384
385                         case READ_CONTROL_ACCESS:
386                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
387
388                         default:        /* no change */
389                                 break;
390                 }
391         }
392
393         /* create a new struct security_descriptor with the appropriate owner and group SIDs */
394
395         new_sec = make_sec_desc( ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
396                                  &global_sid_Builtin_Administrators,
397                                  &global_sid_Builtin_Administrators,
398                                  NULL, NULL, &size_new_sec );
399         if (!new_sec) {
400                 return 0;
401         }
402         sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
403         if (!sd_new) {
404                 return 0;
405         }
406
407         if ( !(sd_store = sec_desc_merge_buf( ctx, sd_new, sd_orig )) ) {
408                 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
409                 return 0;
410         }
411
412         /* store it back */
413
414         sd_size = ndr_size_security_descriptor(sd_store->sd, 0)
415                 + sizeof(struct sec_desc_buf);
416
417         status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
418         if (!NT_STATUS_IS_OK(status)) {
419                 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
420                 return 0;
421         }
422
423         result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
424
425         /* 0 to continue and non-zero to stop traversal */
426
427         return (result == -1);
428 }
429
430 /*******************************************************************
431 *******************************************************************/
432
433 static bool upgrade_to_version_4(void)
434 {
435         TALLOC_CTX *ctx;
436         int result;
437
438         DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
439
440         if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
441                 return False;
442
443         result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
444
445         talloc_destroy( ctx );
446
447         return ( result != -1 );
448 }
449
450 /*******************************************************************
451  Fix an issue with security descriptors.  Printer sec_desc must
452  use more than the generic bits that were previously used
453  in <= 3.0.14a.  They must also have a owner and group SID assigned.
454  Otherwise, any printers than have been migrated to a Windows
455  host using printmig.exe will not be accessible.
456 *******************************************************************/
457
458 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
459                                   TDB_DATA data, void *state )
460 {
461         TALLOC_CTX *ctx = talloc_tos();
462         TDB_DATA new_key;
463
464         if (!data.dptr || data.dsize == 0)
465                 return 0;
466
467         /* upgrade printer records and security descriptors */
468
469         if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
470                 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
471         }
472         else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
473                 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
474         }
475         else {
476                 /* ignore this record */
477                 return 0;
478         }
479
480         /* delete the original record and store under the normalized key */
481
482         if ( tdb_delete( the_tdb, key ) != 0 ) {
483                 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
484                         key.dptr));
485                 return 1;
486         }
487
488         if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
489                 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
490                         key.dptr));
491                 return 1;
492         }
493
494         return 0;
495 }
496
497 /*******************************************************************
498 *******************************************************************/
499
500 static bool upgrade_to_version_5(void)
501 {
502         TALLOC_CTX *ctx;
503         int result;
504
505         DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
506
507         if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
508                 return False;
509
510         result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
511
512         talloc_destroy( ctx );
513
514         return ( result != -1 );
515 }
516
517 /****************************************************************************
518  Open the NT printing tdbs. Done once before fork().
519 ****************************************************************************/
520
521 bool nt_printing_init(struct messaging_context *msg_ctx)
522 {
523         const char *vstring = "INFO/version";
524         WERROR win_rc;
525         int32 vers_id;
526
527         if ( tdb_drivers && tdb_printers && tdb_forms )
528                 return True;
529
530         if (tdb_drivers)
531                 tdb_close(tdb_drivers);
532         tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
533         if (!tdb_drivers) {
534                 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
535                         state_path("ntdrivers.tdb"), strerror(errno) ));
536                 return False;
537         }
538
539         if (tdb_printers)
540                 tdb_close(tdb_printers);
541         tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
542         if (!tdb_printers) {
543                 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
544                         state_path("ntprinters.tdb"), strerror(errno) ));
545                 return False;
546         }
547
548         if (tdb_forms)
549                 tdb_close(tdb_forms);
550         tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
551         if (!tdb_forms) {
552                 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
553                         state_path("ntforms.tdb"), strerror(errno) ));
554                 return False;
555         }
556
557         /* handle a Samba upgrade */
558
559         vers_id = tdb_fetch_int32(tdb_drivers, vstring);
560         if (vers_id == -1) {
561                 DEBUG(10, ("Fresh database\n"));
562                 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
563                 vers_id = NTDRIVERS_DATABASE_VERSION_5;
564         }
565
566         if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
567
568                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
569                         if (!upgrade_to_version_3())
570                                 return False;
571                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
572                         vers_id = NTDRIVERS_DATABASE_VERSION_3;
573                 }
574
575                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
576                         /* Written on a bigendian machine with old fetch_int code. Save as le. */
577                         /* The only upgrade between V2 and V3 is to save the version in little-endian. */
578                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
579                         vers_id = NTDRIVERS_DATABASE_VERSION_3;
580                 }
581
582                 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
583                         if ( !upgrade_to_version_4() )
584                                 return False;
585                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
586                         vers_id = NTDRIVERS_DATABASE_VERSION_4;
587                 }
588
589                 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
590                         if ( !upgrade_to_version_5() )
591                                 return False;
592                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
593                         vers_id = NTDRIVERS_DATABASE_VERSION_5;
594                 }
595
596
597                 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
598                         DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
599                         return False;
600                 }
601         }
602
603         update_c_setprinter(True);
604
605         /*
606          * register callback to handle updating printers as new
607          * drivers are installed
608          */
609
610         messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
611                            do_drv_upgrade_printer);
612
613         /* of course, none of the message callbacks matter if you don't
614            tell messages.c that you interested in receiving PRINT_GENERAL
615            msgs.  This is done in serverid_register() */
616
617
618         if ( lp_security() == SEC_ADS ) {
619                 win_rc = check_published_printers();
620                 if (!W_ERROR_IS_OK(win_rc))
621                         DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
622         }
623
624         return True;
625 }
626
627 /*******************************************************************
628  Function to allow filename parsing "the old way".
629 ********************************************************************/
630
631 static NTSTATUS driver_unix_convert(connection_struct *conn,
632                                     const char *old_name,
633                                     struct smb_filename **smb_fname)
634 {
635         NTSTATUS status;
636         TALLOC_CTX *ctx = talloc_tos();
637         char *name = talloc_strdup(ctx, old_name);
638
639         if (!name) {
640                 return NT_STATUS_NO_MEMORY;
641         }
642         unix_format(name);
643         name = unix_clean_name(ctx, name);
644         if (!name) {
645                 return NT_STATUS_NO_MEMORY;
646         }
647         trim_string(name,"/","/");
648
649         status = unix_convert(ctx, conn, name, smb_fname, 0);
650         if (!NT_STATUS_IS_OK(status)) {
651                 return NT_STATUS_NO_MEMORY;
652         }
653
654         return NT_STATUS_OK;
655 }
656
657 /*******************************************************************
658  tdb traversal function for counting printers.
659 ********************************************************************/
660
661 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
662                                       TDB_DATA data, void *context)
663 {
664         int *printer_count = (int*)context;
665
666         if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
667                 (*printer_count)++;
668                 DEBUG(10,("traverse_counting_printers: printer = [%s]  printer_count = %d\n", key.dptr, *printer_count));
669         }
670
671         return 0;
672 }
673
674 /*******************************************************************
675  Update the spooler global c_setprinter. This variable is initialized
676  when the parent smbd starts with the number of existing printers. It
677  is monotonically increased by the current number of printers *after*
678  each add or delete printer RPC. Only Microsoft knows why... JRR020119
679 ********************************************************************/
680
681 uint32 update_c_setprinter(bool initialize)
682 {
683         int32 c_setprinter;
684         int32 printer_count = 0;
685
686         tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
687
688         /* Traverse the tdb, counting the printers */
689         tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
690
691         /* If initializing, set c_setprinter to current printers count
692          * otherwise, bump it by the current printer count
693          */
694         if (!initialize)
695                 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
696         else
697                 c_setprinter = printer_count;
698
699         DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
700         tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
701
702         tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
703
704         return (uint32)c_setprinter;
705 }
706
707 /*******************************************************************
708  Get the spooler global c_setprinter, accounting for initialization.
709 ********************************************************************/
710
711 uint32 get_c_setprinter(void)
712 {
713         int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
714
715         if (c_setprinter == (int32)-1)
716                 c_setprinter = update_c_setprinter(True);
717
718         DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
719
720         return (uint32)c_setprinter;
721 }
722
723 /****************************************************************************
724  Get builtin form struct list.
725 ****************************************************************************/
726
727 int get_builtin_ntforms(nt_forms_struct **list)
728 {
729         *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
730         if (!*list) {
731                 return 0;
732         }
733         return ARRAY_SIZE(default_forms);
734 }
735
736 /****************************************************************************
737  get a builtin form struct
738 ****************************************************************************/
739
740 bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
741 {
742         int i;
743         DEBUGADD(6,("Looking for builtin form %s \n", form_name));
744         for (i=0; i<ARRAY_SIZE(default_forms); i++) {
745                 if (strequal(form_name,default_forms[i].name)) {
746                         DEBUGADD(6,("Found builtin form %s \n", form_name));
747                         memcpy(form,&default_forms[i],sizeof(*form));
748                         return true;
749                 }
750         }
751
752         return false;
753 }
754
755 /****************************************************************************
756  get a form struct list.
757 ****************************************************************************/
758
759 int get_ntforms(nt_forms_struct **list)
760 {
761         TDB_DATA kbuf, newkey, dbuf;
762         nt_forms_struct form;
763         int ret;
764         int i;
765         int n = 0;
766
767         *list = NULL;
768
769         for (kbuf = tdb_firstkey(tdb_forms);
770              kbuf.dptr;
771              newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
772         {
773                 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
774                         continue;
775
776                 dbuf = tdb_fetch(tdb_forms, kbuf);
777                 if (!dbuf.dptr)
778                         continue;
779
780                 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
781                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
782                                  &i, &form.flag, &form.width, &form.length, &form.left,
783                                  &form.top, &form.right, &form.bottom);
784                 SAFE_FREE(dbuf.dptr);
785                 if (ret != dbuf.dsize)
786                         continue;
787
788                 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
789                 if (!*list) {
790                         DEBUG(0,("get_ntforms: Realloc fail.\n"));
791                         return 0;
792                 }
793                 (*list)[n] = form;
794                 n++;
795         }
796
797
798         return n;
799 }
800
801 /****************************************************************************
802 write a form struct list
803 ****************************************************************************/
804
805 int write_ntforms(nt_forms_struct **list, int number)
806 {
807         TALLOC_CTX *ctx = talloc_tos();
808         char *buf = NULL;
809         char *key = NULL;
810         int len;
811         TDB_DATA dbuf;
812         int i;
813
814         for (i=0;i<number;i++) {
815                 /* save index, so list is rebuilt in correct order */
816                 len = tdb_pack(NULL, 0, "dddddddd",
817                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
818                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
819                                (*list)[i].bottom);
820                 if (!len) {
821                         continue;
822                 }
823                 buf = TALLOC_ARRAY(ctx, char, len);
824                 if (!buf) {
825                         return 0;
826                 }
827                 len = tdb_pack((uint8 *)buf, len, "dddddddd",
828                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
829                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
830                                (*list)[i].bottom);
831                 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
832                 if (!key) {
833                         return 0;
834                 }
835                 dbuf.dsize = len;
836                 dbuf.dptr = (uint8 *)buf;
837                 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
838                         TALLOC_FREE(key);
839                         TALLOC_FREE(buf);
840                         break;
841                 }
842                 TALLOC_FREE(key);
843                 TALLOC_FREE(buf);
844        }
845
846        return i;
847 }
848
849 /****************************************************************************
850 add a form struct at the end of the list
851 ****************************************************************************/
852 bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count)
853 {
854         int n=0;
855         bool update;
856
857         /*
858          * NT tries to add forms even when
859          * they are already in the base
860          * only update the values if already present
861          */
862
863         update=False;
864
865         for (n=0; n<*count; n++) {
866                 if ( strequal((*list)[n].name, form->form_name) ) {
867                         update=True;
868                         break;
869                 }
870         }
871
872         if (update==False) {
873                 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
874                         DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
875                         return False;
876                 }
877                 fstrcpy((*list)[n].name, form->form_name);
878                 (*count)++;
879         }
880
881         (*list)[n].flag         = form->flags;
882         (*list)[n].width        = form->size.width;
883         (*list)[n].length       = form->size.height;
884         (*list)[n].left         = form->area.left;
885         (*list)[n].top          = form->area.top;
886         (*list)[n].right        = form->area.right;
887         (*list)[n].bottom       = form->area.bottom;
888
889         DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
890                 update ? "updated" : "added", form->form_name));
891
892         return True;
893 }
894
895 /****************************************************************************
896  Delete a named form struct.
897 ****************************************************************************/
898
899 bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
900 {
901         char *key = NULL;
902         int n=0;
903
904         *ret = WERR_OK;
905
906         for (n=0; n<*count; n++) {
907                 if (!strncmp((*list)[n].name, del_name, strlen(del_name))) {
908                         DEBUG(103, ("delete_a_form, [%s] in list\n", del_name));
909                         break;
910                 }
911         }
912
913         if (n == *count) {
914                 DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
915                 *ret = WERR_INVALID_FORM_NAME;
916                 return False;
917         }
918
919         if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
920                 *ret = WERR_NOMEM;
921                 return false;
922         }
923         if (tdb_delete_bystring(tdb_forms, key) != 0) {
924                 SAFE_FREE(key);
925                 *ret = WERR_NOMEM;
926                 return False;
927         }
928         SAFE_FREE(key);
929         return true;
930 }
931
932 /****************************************************************************
933  Update a form struct.
934 ****************************************************************************/
935
936 void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
937 {
938         int n=0;
939
940         DEBUG(106, ("[%s]\n", form->form_name));
941         for (n=0; n<count; n++) {
942                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
943                 if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name)))
944                         break;
945         }
946
947         if (n==count) return;
948
949         (*list)[n].flag         = form->flags;
950         (*list)[n].width        = form->size.width;
951         (*list)[n].length       = form->size.height;
952         (*list)[n].left         = form->area.left;
953         (*list)[n].top          = form->area.top;
954         (*list)[n].right        = form->area.right;
955         (*list)[n].bottom       = form->area.bottom;
956 }
957
958 /****************************************************************************
959  Get the nt drivers list.
960  Traverse the database and look-up the matching names.
961 ****************************************************************************/
962 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
963 {
964         int total=0;
965         const char *short_archi;
966         char *key = NULL;
967         TDB_DATA kbuf, newkey;
968
969         short_archi = get_short_archi(architecture);
970         if (!short_archi) {
971                 return 0;
972         }
973
974         if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
975                                 short_archi, version) < 0) {
976                 return 0;
977         }
978
979         for (kbuf = tdb_firstkey(tdb_drivers);
980              kbuf.dptr;
981              newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
982
983                 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
984                         continue;
985
986                 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
987                         DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
988                         SAFE_FREE(key);
989                         return -1;
990                 }
991
992                 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
993                 total++;
994         }
995
996         SAFE_FREE(key);
997         return(total);
998 }
999
1000 /****************************************************************************
1001  Function to do the mapping between the long architecture name and
1002  the short one.
1003 ****************************************************************************/
1004
1005 const char *get_short_archi(const char *long_archi)
1006 {
1007         int i=-1;
1008
1009         DEBUG(107,("Getting architecture dependant directory\n"));
1010         do {
1011                 i++;
1012         } while ( (archi_table[i].long_archi!=NULL ) &&
1013                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
1014
1015         if (archi_table[i].long_archi==NULL) {
1016                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1017                 return NULL;
1018         }
1019
1020         /* this might be client code - but shouldn't this be an fstrcpy etc? */
1021
1022         DEBUGADD(108,("index: [%d]\n", i));
1023         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1024         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1025
1026         return archi_table[i].short_archi;
1027 }
1028
1029 /****************************************************************************
1030  Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1031  There are two case to be covered here: PE (Portable Executable) and NE (New
1032  Executable) files. Both files support the same INFO structure, but PE files
1033  store the signature in unicode, and NE files store it as !unicode.
1034  returns -1 on error, 1 on version info found, and 0 on no version info found.
1035 ****************************************************************************/
1036
1037 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1038 {
1039         int     i;
1040         char    *buf = NULL;
1041         ssize_t byte_count;
1042
1043         if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1044                 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1045                                 fname, DOS_HEADER_SIZE));
1046                 goto error_exit;
1047         }
1048
1049         if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1050                 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1051                          fname, (unsigned long)byte_count));
1052                 goto no_version_info;
1053         }
1054
1055         /* Is this really a DOS header? */
1056         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1057                 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1058                                 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1059                 goto no_version_info;
1060         }
1061
1062         /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1063         if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1064                 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1065                                 fname, errno));
1066                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1067                 goto no_version_info;
1068         }
1069
1070         /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1071         if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1072                 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1073                          fname, (unsigned long)byte_count));
1074                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1075                 goto no_version_info;
1076         }
1077
1078         /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1079         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1080                 unsigned int num_sections;
1081                 unsigned int section_table_bytes;
1082
1083                 /* Just skip over optional header to get to section table */
1084                 if (SMB_VFS_LSEEK(fsp,
1085                                 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1086                                 SEEK_CUR) == (SMB_OFF_T)-1) {
1087                         DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1088                                 fname, errno));
1089                         goto error_exit;
1090                 }
1091
1092                 /* get the section table */
1093                 num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1094                 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1095                 if (section_table_bytes == 0)
1096                         goto error_exit;
1097
1098                 SAFE_FREE(buf);
1099                 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1100                         DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1101                                         fname, section_table_bytes));
1102                         goto error_exit;
1103                 }
1104
1105                 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1106                         DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1107                                  fname, (unsigned long)byte_count));
1108                         goto error_exit;
1109                 }
1110
1111                 /* Iterate the section table looking for the resource section ".rsrc" */
1112                 for (i = 0; i < num_sections; i++) {
1113                         int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1114
1115                         if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1116                                 unsigned int section_pos   = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1117                                 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1118
1119                                 if (section_bytes == 0)
1120                                         goto error_exit;
1121
1122                                 SAFE_FREE(buf);
1123                                 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1124                                         DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1125                                                         fname, section_bytes));
1126                                         goto error_exit;
1127                                 }
1128
1129                                 /* Seek to the start of the .rsrc section info */
1130                                 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1131                                         DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1132                                                         fname, errno));
1133                                         goto error_exit;
1134                                 }
1135
1136                                 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1137                                         DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1138                                                  fname, (unsigned long)byte_count));
1139                                         goto error_exit;
1140                                 }
1141
1142                                 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1143                                         goto error_exit;
1144
1145                                 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1146                                         /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1147                                         if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1148                                                 /* Align to next long address */
1149                                                 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1150
1151                                                 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1152                                                         *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1153                                                         *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1154
1155                                                         DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1156                                                                           fname, *major, *minor,
1157                                                                           (*major>>16)&0xffff, *major&0xffff,
1158                                                                           (*minor>>16)&0xffff, *minor&0xffff));
1159                                                         SAFE_FREE(buf);
1160                                                         return 1;
1161                                                 }
1162                                         }
1163                                 }
1164                         }
1165                 }
1166
1167                 /* Version info not found, fall back to origin date/time */
1168                 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1169                 SAFE_FREE(buf);
1170                 return 0;
1171
1172         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1173                 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1174                         DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1175                                         fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1176                         /* At this point, we assume the file is in error. It still could be somthing
1177                          * else besides a NE file, but it unlikely at this point. */
1178                         goto error_exit;
1179                 }
1180
1181                 /* Allocate a bit more space to speed up things */
1182                 SAFE_FREE(buf);
1183                 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1184                         DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes  = %d\n",
1185                                         fname, PE_HEADER_SIZE));
1186                         goto error_exit;
1187                 }
1188
1189                 /* This is a HACK! I got tired of trying to sort through the messy
1190                  * 'NE' file format. If anyone wants to clean this up please have at
1191                  * it, but this works. 'NE' files will eventually fade away. JRR */
1192                 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1193                         /* Cover case that should not occur in a well formed 'NE' .dll file */
1194                         if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1195
1196                         for(i=0; i<byte_count; i++) {
1197                                 /* Fast skip past data that can't possibly match */
1198                                 if (buf[i] != 'V') continue;
1199
1200                                 /* Potential match data crosses buf boundry, move it to beginning
1201                                  * of buf, and fill the buf with as much as it will hold. */
1202                                 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1203                                         int bc;
1204
1205                                         memcpy(buf, &buf[i], byte_count-i);
1206                                         if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1207                                                                    (byte_count-i))) < 0) {
1208
1209                                                 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1210                                                                  fname, errno));
1211                                                 goto error_exit;
1212                                         }
1213
1214                                         byte_count = bc + (byte_count - i);
1215                                         if (byte_count<VS_VERSION_INFO_SIZE) break;
1216
1217                                         i = 0;
1218                                 }
1219
1220                                 /* Check that the full signature string and the magic number that
1221                                  * follows exist (not a perfect solution, but the chances that this
1222                                  * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1223                                  * twice, as it is simpler to read the code. */
1224                                 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1225                                         /* Compute skip alignment to next long address */
1226                                         int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1227                                                                  sizeof(VS_SIGNATURE)) & 3;
1228                                         if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1229
1230                                         *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1231                                         *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1232                                         DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1233                                                           fname, *major, *minor,
1234                                                           (*major>>16)&0xffff, *major&0xffff,
1235                                                           (*minor>>16)&0xffff, *minor&0xffff));
1236                                         SAFE_FREE(buf);
1237                                         return 1;
1238                                 }
1239                         }
1240                 }
1241
1242                 /* Version info not found, fall back to origin date/time */
1243                 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1244                 SAFE_FREE(buf);
1245                 return 0;
1246
1247         } else
1248                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1249                 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1250                                 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1251
1252         no_version_info:
1253                 SAFE_FREE(buf);
1254                 return 0;
1255
1256         error_exit:
1257                 SAFE_FREE(buf);
1258                 return -1;
1259 }
1260
1261 /****************************************************************************
1262 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1263 share one or more files. During the MS installation process files are checked
1264 to insure that only a newer version of a shared file is installed over an
1265 older version. There are several possibilities for this comparison. If there
1266 is no previous version, the new one is newer (obviously). If either file is
1267 missing the version info structure, compare the creation date (on Unix use
1268 the modification date). Otherwise chose the numerically larger version number.
1269 ****************************************************************************/
1270
1271 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1272 {
1273         bool use_version = true;
1274
1275         uint32 new_major;
1276         uint32 new_minor;
1277         time_t new_create_time;
1278
1279         uint32 old_major;
1280         uint32 old_minor;
1281         time_t old_create_time;
1282
1283         struct smb_filename *smb_fname = NULL;
1284         files_struct    *fsp = NULL;
1285         SMB_STRUCT_STAT st;
1286
1287         NTSTATUS status;
1288         int ret;
1289
1290         SET_STAT_INVALID(st);
1291         new_create_time = (time_t)0;
1292         old_create_time = (time_t)0;
1293
1294         /* Get file version info (if available) for previous file (if it exists) */
1295         status = driver_unix_convert(conn, old_file, &smb_fname);
1296         if (!NT_STATUS_IS_OK(status)) {
1297                 goto error_exit;
1298         }
1299
1300         status = SMB_VFS_CREATE_FILE(
1301                 conn,                                   /* conn */
1302                 NULL,                                   /* req */
1303                 0,                                      /* root_dir_fid */
1304                 smb_fname,                              /* fname */
1305                 FILE_GENERIC_READ,                      /* access_mask */
1306                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
1307                 FILE_OPEN,                              /* create_disposition*/
1308                 0,                                      /* create_options */
1309                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
1310                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
1311                 0,                                      /* allocation_size */
1312                 0,                                      /* private_flags */
1313                 NULL,                                   /* sd */
1314                 NULL,                                   /* ea_list */
1315                 &fsp,                                   /* result */
1316                 NULL);                                  /* pinfo */
1317
1318         if (!NT_STATUS_IS_OK(status)) {
1319                 /* Old file not found, so by definition new file is in fact newer */
1320                 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
1321                           "errno = %d\n", smb_fname_str_dbg(smb_fname),
1322                           errno));
1323                 ret = 1;
1324                 goto done;
1325
1326         } else {
1327                 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1328                 if (ret == -1) {
1329                         goto error_exit;
1330                 }
1331
1332                 if (!ret) {
1333                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1334                                          old_file));
1335                         use_version = false;
1336                         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1337                                  goto error_exit;
1338                         }
1339                         old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1340                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1341                                 (long)old_create_time));
1342                 }
1343         }
1344         close_file(NULL, fsp, NORMAL_CLOSE);
1345         fsp = NULL;
1346
1347         /* Get file version info (if available) for new file */
1348         status = driver_unix_convert(conn, new_file, &smb_fname);
1349         if (!NT_STATUS_IS_OK(status)) {
1350                 goto error_exit;
1351         }
1352
1353         status = SMB_VFS_CREATE_FILE(
1354                 conn,                                   /* conn */
1355                 NULL,                                   /* req */
1356                 0,                                      /* root_dir_fid */
1357                 smb_fname,                              /* fname */
1358                 FILE_GENERIC_READ,                      /* access_mask */
1359                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
1360                 FILE_OPEN,                              /* create_disposition*/
1361                 0,                                      /* create_options */
1362                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
1363                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
1364                 0,                                      /* allocation_size */
1365                 0,                                      /* private_flags */
1366                 NULL,                                   /* sd */
1367                 NULL,                                   /* ea_list */
1368                 &fsp,                                   /* result */
1369                 NULL);                                  /* pinfo */
1370
1371         if (!NT_STATUS_IS_OK(status)) {
1372                 /* New file not found, this shouldn't occur if the caller did its job */
1373                 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
1374                          "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
1375                 goto error_exit;
1376
1377         } else {
1378                 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1379                 if (ret == -1) {
1380                         goto error_exit;
1381                 }
1382
1383                 if (!ret) {
1384                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1385                                          new_file));
1386                         use_version = false;
1387                         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1388                                 goto error_exit;
1389                         }
1390                         new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1391                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1392                                 (long)new_create_time));
1393                 }
1394         }
1395         close_file(NULL, fsp, NORMAL_CLOSE);
1396         fsp = NULL;
1397
1398         if (use_version && (new_major != old_major || new_minor != old_minor)) {
1399                 /* Compare versions and choose the larger version number */
1400                 if (new_major > old_major ||
1401                         (new_major == old_major && new_minor > old_minor)) {
1402
1403                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1404                         ret = 1;
1405                         goto done;
1406                 }
1407                 else {
1408                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1409                         ret = 0;
1410                         goto done;
1411                 }
1412
1413         } else {
1414                 /* Compare modification time/dates and choose the newest time/date */
1415                 if (new_create_time > old_create_time) {
1416                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1417                         ret = 1;
1418                         goto done;
1419                 }
1420                 else {
1421                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1422                         ret = 0;
1423                         goto done;
1424                 }
1425         }
1426
1427  error_exit:
1428         if(fsp)
1429                 close_file(NULL, fsp, NORMAL_CLOSE);
1430         ret = -1;
1431  done:
1432         TALLOC_FREE(smb_fname);
1433         return ret;
1434 }
1435
1436 /****************************************************************************
1437 Determine the correct cVersion associated with an architecture and driver
1438 ****************************************************************************/
1439 static uint32 get_correct_cversion(struct pipes_struct *p,
1440                                    const char *architecture,
1441                                    const char *driverpath_in,
1442                                    WERROR *perr)
1443 {
1444         int               cversion;
1445         NTSTATUS          nt_status;
1446         struct smb_filename *smb_fname = NULL;
1447         char *driverpath = NULL;
1448         files_struct      *fsp = NULL;
1449         connection_struct *conn = NULL;
1450         NTSTATUS status;
1451         char *oldcwd;
1452         fstring printdollar;
1453         int printdollar_snum;
1454
1455         *perr = WERR_INVALID_PARAM;
1456
1457         /* If architecture is Windows 95/98/ME, the version is always 0. */
1458         if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1459                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1460                 *perr = WERR_OK;
1461                 return 0;
1462         }
1463
1464         /* If architecture is Windows x64, the version is always 3. */
1465         if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1466                 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1467                 *perr = WERR_OK;
1468                 return 3;
1469         }
1470
1471         fstrcpy(printdollar, "print$");
1472
1473         printdollar_snum = find_service(printdollar);
1474         if (printdollar_snum == -1) {
1475                 *perr = WERR_NO_SUCH_SHARE;
1476                 return -1;
1477         }
1478
1479         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1480                                        lp_pathname(printdollar_snum),
1481                                        p->server_info, &oldcwd);
1482         if (!NT_STATUS_IS_OK(nt_status)) {
1483                 DEBUG(0,("get_correct_cversion: create_conn_struct "
1484                          "returned %s\n", nt_errstr(nt_status)));
1485                 *perr = ntstatus_to_werror(nt_status);
1486                 return -1;
1487         }
1488
1489         /* Open the driver file (Portable Executable format) and determine the
1490          * deriver the cversion. */
1491         driverpath = talloc_asprintf(talloc_tos(),
1492                                         "%s/%s",
1493                                         architecture,
1494                                         driverpath_in);
1495         if (!driverpath) {
1496                 *perr = WERR_NOMEM;
1497                 goto error_exit;
1498         }
1499
1500         nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
1501         if (!NT_STATUS_IS_OK(nt_status)) {
1502                 *perr = ntstatus_to_werror(nt_status);
1503                 goto error_exit;
1504         }
1505
1506         nt_status = vfs_file_exist(conn, smb_fname);
1507         if (!NT_STATUS_IS_OK(nt_status)) {
1508                 *perr = WERR_BADFILE;
1509                 goto error_exit;
1510         }
1511
1512         status = SMB_VFS_CREATE_FILE(
1513                 conn,                                   /* conn */
1514                 NULL,                                   /* req */
1515                 0,                                      /* root_dir_fid */
1516                 smb_fname,                              /* fname */
1517                 FILE_GENERIC_READ,                      /* access_mask */
1518                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
1519                 FILE_OPEN,                              /* create_disposition*/
1520                 0,                                      /* create_options */
1521                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
1522                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
1523                 0,                                      /* private_flags */
1524                 0,                                      /* allocation_size */
1525                 NULL,                                   /* sd */
1526                 NULL,                                   /* ea_list */
1527                 &fsp,                                   /* result */
1528                 NULL);                                  /* pinfo */
1529
1530         if (!NT_STATUS_IS_OK(status)) {
1531                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1532                          "%d\n", smb_fname_str_dbg(smb_fname), errno));
1533                 *perr = WERR_ACCESS_DENIED;
1534                 goto error_exit;
1535         } else {
1536                 uint32 major;
1537                 uint32 minor;
1538                 int    ret;
1539
1540                 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1541                 if (ret == -1) goto error_exit;
1542
1543                 if (!ret) {
1544                         DEBUG(6,("get_correct_cversion: Version info not "
1545                                  "found [%s]\n",
1546                                  smb_fname_str_dbg(smb_fname)));
1547                         goto error_exit;
1548                 }
1549
1550                 /*
1551                  * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1552                  * for more details. Version in this case is not just the version of the
1553                  * file, but the version in the sense of kernal mode (2) vs. user mode
1554                  * (3) drivers. Other bits of the version fields are the version info.
1555                  * JRR 010716
1556                 */
1557                 cversion = major & 0x0000ffff;
1558                 switch (cversion) {
1559                         case 2: /* WinNT drivers */
1560                         case 3: /* Win2K drivers */
1561                                 break;
1562
1563                         default:
1564                                 DEBUG(6,("get_correct_cversion: cversion "
1565                                          "invalid [%s]  cversion = %d\n",
1566                                          smb_fname_str_dbg(smb_fname),
1567                                          cversion));
1568                                 goto error_exit;
1569                 }
1570
1571                 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1572                           " = 0x%x  minor = 0x%x\n",
1573                           smb_fname_str_dbg(smb_fname), major, minor));
1574         }
1575
1576         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1577                   smb_fname_str_dbg(smb_fname), cversion));
1578
1579         goto done;
1580
1581  error_exit:
1582         cversion = -1;
1583  done:
1584         TALLOC_FREE(smb_fname);
1585         if (fsp != NULL) {
1586                 close_file(NULL, fsp, NORMAL_CLOSE);
1587         }
1588         if (conn != NULL) {
1589                 vfs_ChDir(conn, oldcwd);
1590                 conn_free(conn);
1591         }
1592         if (cversion != -1) {
1593                 *perr = WERR_OK;
1594         }
1595         return cversion;
1596 }
1597
1598 /****************************************************************************
1599 ****************************************************************************/
1600
1601 #define strip_driver_path(_mem_ctx, _element) do { \
1602         if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1603                 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1604                 W_ERROR_HAVE_NO_MEMORY((_element)); \
1605         } \
1606 } while (0);
1607
1608 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1609                                            struct pipes_struct *rpc_pipe,
1610                                            const char *architecture,
1611                                            const char **driver_path,
1612                                            const char **data_file,
1613                                            const char **config_file,
1614                                            const char **help_file,
1615                                            struct spoolss_StringArray *dependent_files,
1616                                            uint32_t *version)
1617 {
1618         const char *short_architecture;
1619         int i;
1620         WERROR err;
1621         char *_p;
1622
1623         if (!*driver_path || !*data_file || !*config_file) {
1624                 return WERR_INVALID_PARAM;
1625         }
1626
1627         /* clean up the driver name.
1628          * we can get .\driver.dll
1629          * or worse c:\windows\system\driver.dll !
1630          */
1631         /* using an intermediate string to not have overlaping memcpy()'s */
1632
1633         strip_driver_path(mem_ctx, *driver_path);
1634         strip_driver_path(mem_ctx, *data_file);
1635         strip_driver_path(mem_ctx, *config_file);
1636         if (help_file) {
1637                 strip_driver_path(mem_ctx, *help_file);
1638         }
1639
1640         if (dependent_files && dependent_files->string) {
1641                 for (i=0; dependent_files->string[i]; i++) {
1642                         strip_driver_path(mem_ctx, dependent_files->string[i]);
1643                 }
1644         }
1645
1646         short_architecture = get_short_archi(architecture);
1647         if (!short_architecture) {
1648                 return WERR_UNKNOWN_PRINTER_DRIVER;
1649         }
1650
1651         /* jfm:7/16/2000 the client always sends the cversion=0.
1652          * The server should check which version the driver is by reading
1653          * the PE header of driver->driverpath.
1654          *
1655          * For Windows 95/98 the version is 0 (so the value sent is correct)
1656          * For Windows NT (the architecture doesn't matter)
1657          *      NT 3.1: cversion=0
1658          *      NT 3.5/3.51: cversion=1
1659          *      NT 4: cversion=2
1660          *      NT2K: cversion=3
1661          */
1662
1663         *version = get_correct_cversion(rpc_pipe, short_architecture,
1664                                         *driver_path, &err);
1665         if (*version == -1) {
1666                 return err;
1667         }
1668
1669         return WERR_OK;
1670 }
1671
1672 /****************************************************************************
1673 ****************************************************************************/
1674
1675 WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe,
1676                               struct spoolss_AddDriverInfoCtr *r)
1677 {
1678         switch (r->level) {
1679         case 3:
1680                 return clean_up_driver_struct_level(r, rpc_pipe,
1681                                                     r->info.info3->architecture,
1682                                                     &r->info.info3->driver_path,
1683                                                     &r->info.info3->data_file,
1684                                                     &r->info.info3->config_file,
1685                                                     &r->info.info3->help_file,
1686                                                     r->info.info3->dependent_files,
1687                                                     &r->info.info3->version);
1688         case 6:
1689                 return clean_up_driver_struct_level(r, rpc_pipe,
1690                                                     r->info.info6->architecture,
1691                                                     &r->info.info6->driver_path,
1692                                                     &r->info.info6->data_file,
1693                                                     &r->info.info6->config_file,
1694                                                     &r->info.info6->help_file,
1695                                                     r->info.info6->dependent_files,
1696                                                     &r->info.info6->version);
1697         default:
1698                 return WERR_NOT_SUPPORTED;
1699         }
1700 }
1701
1702 /****************************************************************************
1703  This function sucks and should be replaced. JRA.
1704 ****************************************************************************/
1705
1706 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1707                                       const struct spoolss_AddDriverInfo6 *src)
1708 {
1709         dst->version            = src->version;
1710
1711         dst->driver_name        = src->driver_name;
1712         dst->architecture       = src->architecture;
1713         dst->driver_path        = src->driver_path;
1714         dst->data_file          = src->data_file;
1715         dst->config_file        = src->config_file;
1716         dst->help_file          = src->help_file;
1717         dst->monitor_name       = src->monitor_name;
1718         dst->default_datatype   = src->default_datatype;
1719         dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1720         dst->dependent_files    = src->dependent_files;
1721 }
1722
1723 /****************************************************************************
1724  This function sucks and should be replaced. JRA.
1725 ****************************************************************************/
1726
1727 static void convert_level_8_to_level3(TALLOC_CTX *mem_ctx,
1728                                       struct spoolss_AddDriverInfo3 *dst,
1729                                       const struct spoolss_DriverInfo8 *src)
1730 {
1731         dst->version            = src->version;
1732         dst->driver_name        = src->driver_name;
1733         dst->architecture       = src->architecture;
1734         dst->driver_path        = src->driver_path;
1735         dst->data_file          = src->data_file;
1736         dst->config_file        = src->config_file;
1737         dst->help_file          = src->help_file;
1738         dst->monitor_name       = src->monitor_name;
1739         dst->default_datatype   = src->default_datatype;
1740         if (src->dependent_files) {
1741                 dst->dependent_files = talloc_zero(mem_ctx, struct spoolss_StringArray);
1742                 if (!dst->dependent_files) return;
1743                 dst->dependent_files->string = src->dependent_files;
1744         } else {
1745                 dst->dependent_files = NULL;
1746         }
1747 }
1748
1749 /****************************************************************************
1750 ****************************************************************************/
1751
1752 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1753                                                 connection_struct *conn,
1754                                                 const char *driver_file,
1755                                                 const char *short_architecture,
1756                                                 uint32_t driver_version,
1757                                                 uint32_t version)
1758 {
1759         struct smb_filename *smb_fname_old = NULL;
1760         struct smb_filename *smb_fname_new = NULL;
1761         char *old_name = NULL;
1762         char *new_name = NULL;
1763         NTSTATUS status;
1764         WERROR ret;
1765
1766         old_name = talloc_asprintf(mem_ctx, "%s/%s",
1767                                    short_architecture, driver_file);
1768         W_ERROR_HAVE_NO_MEMORY(old_name);
1769
1770         new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1771                                    short_architecture, driver_version, driver_file);
1772         if (new_name == NULL) {
1773                 TALLOC_FREE(old_name);
1774                 return WERR_NOMEM;
1775         }
1776
1777         if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1778
1779                 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1780                 if (!NT_STATUS_IS_OK(status)) {
1781                         ret = WERR_NOMEM;
1782                         goto out;
1783                 }
1784
1785                 /* Setup a synthetic smb_filename struct */
1786                 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
1787                 if (!smb_fname_new) {
1788                         ret = WERR_NOMEM;
1789                         goto out;
1790                 }
1791
1792                 smb_fname_new->base_name = new_name;
1793
1794                 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1795                           "'%s'\n", smb_fname_old->base_name,
1796                           smb_fname_new->base_name));
1797
1798                 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1799                                    OPENX_FILE_EXISTS_TRUNCATE |
1800                                    OPENX_FILE_CREATE_IF_NOT_EXIST,
1801                                    0, false);
1802
1803                 if (!NT_STATUS_IS_OK(status)) {
1804                         DEBUG(0,("move_driver_file_to_download_area: Unable "
1805                                  "to rename [%s] to [%s]: %s\n",
1806                                  smb_fname_old->base_name, new_name,
1807                                  nt_errstr(status)));
1808                         ret = WERR_ACCESS_DENIED;
1809                         goto out;
1810                 }
1811         }
1812
1813         ret = WERR_OK;
1814  out:
1815         TALLOC_FREE(smb_fname_old);
1816         TALLOC_FREE(smb_fname_new);
1817         return ret;
1818 }
1819
1820 WERROR move_driver_to_download_area(struct pipes_struct *p,
1821                                     struct spoolss_AddDriverInfoCtr *r,
1822                                     WERROR *perr)
1823 {
1824         struct spoolss_AddDriverInfo3 *driver;
1825         struct spoolss_AddDriverInfo3 converted_driver;
1826         const char *short_architecture;
1827         struct smb_filename *smb_dname = NULL;
1828         char *new_dir = NULL;
1829         connection_struct *conn = NULL;
1830         NTSTATUS nt_status;
1831         int i;
1832         TALLOC_CTX *ctx = talloc_tos();
1833         int ver = 0;
1834         char *oldcwd;
1835         fstring printdollar;
1836         int printdollar_snum;
1837
1838         *perr = WERR_OK;
1839
1840         switch (r->level) {
1841         case 3:
1842                 driver = r->info.info3;
1843                 break;
1844         case 6:
1845                 convert_level_6_to_level3(&converted_driver, r->info.info6);
1846                 driver = &converted_driver;
1847                 break;
1848         default:
1849                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1850                 return WERR_UNKNOWN_LEVEL;
1851         }
1852
1853         short_architecture = get_short_archi(driver->architecture);
1854         if (!short_architecture) {
1855                 return WERR_UNKNOWN_PRINTER_DRIVER;
1856         }
1857
1858         fstrcpy(printdollar, "print$");
1859
1860         printdollar_snum = find_service(printdollar);
1861         if (printdollar_snum == -1) {
1862                 *perr = WERR_NO_SUCH_SHARE;
1863                 return WERR_NO_SUCH_SHARE;
1864         }
1865
1866         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1867                                        lp_pathname(printdollar_snum),
1868                                        p->server_info, &oldcwd);
1869         if (!NT_STATUS_IS_OK(nt_status)) {
1870                 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1871                          "returned %s\n", nt_errstr(nt_status)));
1872                 *perr = ntstatus_to_werror(nt_status);
1873                 return *perr;
1874         }
1875
1876         new_dir = talloc_asprintf(ctx,
1877                                 "%s/%d",
1878                                 short_architecture,
1879                                 driver->version);
1880         if (!new_dir) {
1881                 *perr = WERR_NOMEM;
1882                 goto err_exit;
1883         }
1884         nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1885         if (!NT_STATUS_IS_OK(nt_status)) {
1886                 *perr = WERR_NOMEM;
1887                 goto err_exit;
1888         }
1889
1890         DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1891
1892         create_directory(conn, NULL, smb_dname);
1893
1894         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1895          * listed for this driver which has already been moved, skip it (note:
1896          * drivers may list the same file name several times. Then check if the
1897          * file already exists in archi\version\, if so, check that the version
1898          * info (or time stamps if version info is unavailable) is newer (or the
1899          * date is later). If it is, move it to archi\version\filexxx.yyy.
1900          * Otherwise, delete the file.
1901          *
1902          * If a file is not moved to archi\version\ because of an error, all the
1903          * rest of the 'unmoved' driver files are removed from archi\. If one or
1904          * more of the driver's files was already moved to archi\version\, it
1905          * potentially leaves the driver in a partially updated state. Version
1906          * trauma will most likely occur if an client attempts to use any printer
1907          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1908          * done is appropriate... later JRR
1909          */
1910
1911         DEBUG(5,("Moving files now !\n"));
1912
1913         if (driver->driver_path && strlen(driver->driver_path)) {
1914
1915                 *perr = move_driver_file_to_download_area(ctx,
1916                                                           conn,
1917                                                           driver->driver_path,
1918                                                           short_architecture,
1919                                                           driver->version,
1920                                                           ver);
1921                 if (!W_ERROR_IS_OK(*perr)) {
1922                         if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1923                                 ver = -1;
1924                         }
1925                         goto err_exit;
1926                 }
1927         }
1928
1929         if (driver->data_file && strlen(driver->data_file)) {
1930                 if (!strequal(driver->data_file, driver->driver_path)) {
1931
1932                         *perr = move_driver_file_to_download_area(ctx,
1933                                                                   conn,
1934                                                                   driver->data_file,
1935                                                                   short_architecture,
1936                                                                   driver->version,
1937                                                                   ver);
1938                         if (!W_ERROR_IS_OK(*perr)) {
1939                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1940                                         ver = -1;
1941                                 }
1942                                 goto err_exit;
1943                         }
1944                 }
1945         }
1946
1947         if (driver->config_file && strlen(driver->config_file)) {
1948                 if (!strequal(driver->config_file, driver->driver_path) &&
1949                     !strequal(driver->config_file, driver->data_file)) {
1950
1951                         *perr = move_driver_file_to_download_area(ctx,
1952                                                                   conn,
1953                                                                   driver->config_file,
1954                                                                   short_architecture,
1955                                                                   driver->version,
1956                                                                   ver);
1957                         if (!W_ERROR_IS_OK(*perr)) {
1958                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1959                                         ver = -1;
1960                                 }
1961                                 goto err_exit;
1962                         }
1963                 }
1964         }
1965
1966         if (driver->help_file && strlen(driver->help_file)) {
1967                 if (!strequal(driver->help_file, driver->driver_path) &&
1968                     !strequal(driver->help_file, driver->data_file) &&
1969                     !strequal(driver->help_file, driver->config_file)) {
1970
1971                         *perr = move_driver_file_to_download_area(ctx,
1972                                                                   conn,
1973                                                                   driver->help_file,
1974                                                                   short_architecture,
1975                                                                   driver->version,
1976                                                                   ver);
1977                         if (!W_ERROR_IS_OK(*perr)) {
1978                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1979                                         ver = -1;
1980                                 }
1981                                 goto err_exit;
1982                         }
1983                 }
1984         }
1985
1986         if (driver->dependent_files && driver->dependent_files->string) {
1987                 for (i=0; driver->dependent_files->string[i]; i++) {
1988                         if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1989                             !strequal(driver->dependent_files->string[i], driver->data_file) &&
1990                             !strequal(driver->dependent_files->string[i], driver->config_file) &&
1991                             !strequal(driver->dependent_files->string[i], driver->help_file)) {
1992                                 int j;
1993                                 for (j=0; j < i; j++) {
1994                                         if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1995                                                 goto NextDriver;
1996                                         }
1997                                 }
1998
1999                                 *perr = move_driver_file_to_download_area(ctx,
2000                                                                           conn,
2001                                                                           driver->dependent_files->string[i],
2002                                                                           short_architecture,
2003                                                                           driver->version,
2004                                                                           ver);
2005                                 if (!W_ERROR_IS_OK(*perr)) {
2006                                         if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
2007                                                 ver = -1;
2008                                         }
2009                                         goto err_exit;
2010                                 }
2011                         }
2012                 NextDriver: ;
2013                 }
2014         }
2015
2016   err_exit:
2017         TALLOC_FREE(smb_dname);
2018
2019         if (conn != NULL) {
2020                 vfs_ChDir(conn, oldcwd);
2021                 conn_free(conn);
2022         }
2023
2024         if (W_ERROR_EQUAL(*perr, WERR_OK)) {
2025                 return WERR_OK;
2026         }
2027         if (ver == -1) {
2028                 return WERR_UNKNOWN_PRINTER_DRIVER;
2029         }
2030         return (*perr);
2031 }
2032
2033 /****************************************************************************
2034 ****************************************************************************/
2035
2036 static uint32 add_a_printer_driver_3(struct spoolss_AddDriverInfo3 *driver)
2037 {
2038         TALLOC_CTX *ctx = talloc_tos();
2039         int len, buflen;
2040         const char *architecture;
2041         char *directory = NULL;
2042         char *key = NULL;
2043         uint8 *buf;
2044         int i, ret;
2045         TDB_DATA dbuf;
2046
2047         architecture = get_short_archi(driver->architecture);
2048         if (!architecture) {
2049                 return (uint32)-1;
2050         }
2051
2052         /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2053          * \\server is added in the rpc server layer.
2054          * It does make sense to NOT store the server's name in the printer TDB.
2055          */
2056
2057         directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
2058                         architecture, driver->version);
2059         if (!directory) {
2060                 return (uint32)-1;
2061         }
2062
2063 #define gen_full_driver_unc_path(ctx, directory, file) \
2064         do { \
2065                 if (file && strlen(file)) { \
2066                         file = talloc_asprintf(ctx, "%s%s", directory, file); \
2067                 } else { \
2068                         file = talloc_strdup(ctx, ""); \
2069                 } \
2070                 if (!file) { \
2071                         return (uint32_t)-1; \
2072                 } \
2073         } while (0);
2074
2075         /* .inf files do not always list a file for each of the four standard files.
2076          * Don't prepend a path to a null filename, or client claims:
2077          *   "The server on which the printer resides does not have a suitable
2078          *   <printer driver name> printer driver installed. Click OK if you
2079          *   wish to install the driver on your local machine."
2080          */
2081
2082         gen_full_driver_unc_path(ctx, directory, driver->driver_path);
2083         gen_full_driver_unc_path(ctx, directory, driver->data_file);
2084         gen_full_driver_unc_path(ctx, directory, driver->config_file);
2085         gen_full_driver_unc_path(ctx, directory, driver->help_file);
2086
2087         if (driver->dependent_files && driver->dependent_files->string) {
2088                 for (i=0; driver->dependent_files->string[i]; i++) {
2089                         gen_full_driver_unc_path(ctx, directory,
2090                                 driver->dependent_files->string[i]);
2091                 }
2092         }
2093
2094         key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
2095                         architecture, driver->version, driver->driver_name);
2096         if (!key) {
2097                 return (uint32)-1;
2098         }
2099
2100         DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
2101
2102         buf = NULL;
2103         len = buflen = 0;
2104
2105  again:
2106         len = 0;
2107         len += tdb_pack(buf+len, buflen-len, "dffffffff",
2108                         driver->version,
2109                         driver->driver_name,
2110                         driver->architecture,
2111                         driver->driver_path,
2112                         driver->data_file,
2113                         driver->config_file,
2114                         driver->help_file,
2115                         driver->monitor_name ? driver->monitor_name : "",
2116                         driver->default_datatype ? driver->default_datatype : "");
2117
2118         if (driver->dependent_files && driver->dependent_files->string) {
2119                 for (i=0; driver->dependent_files->string[i]; i++) {
2120                         len += tdb_pack(buf+len, buflen-len, "f",
2121                                         driver->dependent_files->string[i]);
2122                 }
2123         }
2124
2125         if (len != buflen) {
2126                 buf = (uint8 *)SMB_REALLOC(buf, len);
2127                 if (!buf) {
2128                         DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2129                         ret = -1;
2130                         goto done;
2131                 }
2132                 buflen = len;
2133                 goto again;
2134         }
2135
2136         dbuf.dptr = buf;
2137         dbuf.dsize = len;
2138
2139         ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2140
2141 done:
2142         if (ret)
2143                 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2144
2145         SAFE_FREE(buf);
2146         return ret;
2147 }
2148
2149 /****************************************************************************
2150 ****************************************************************************/
2151
2152 static uint32_t add_a_printer_driver_8(struct spoolss_DriverInfo8 *driver)
2153 {
2154         TALLOC_CTX *mem_ctx = talloc_new(talloc_tos());
2155         struct spoolss_AddDriverInfo3 info3;
2156         uint32_t ret;
2157
2158         convert_level_8_to_level3(mem_ctx, &info3, driver);
2159
2160         ret = add_a_printer_driver_3(&info3);
2161         talloc_free(mem_ctx);
2162
2163         return ret;
2164 }
2165
2166 /****************************************************************************
2167 ****************************************************************************/
2168
2169 static WERROR get_a_printer_driver_3_default(TALLOC_CTX *mem_ctx,
2170                                              struct spoolss_DriverInfo3 *info,
2171                                              const char *driver, const char *arch)
2172 {
2173         info->driver_name = talloc_strdup(mem_ctx, driver);
2174         if (!info->driver_name) {
2175                 return WERR_NOMEM;
2176         }
2177
2178         info->default_datatype = talloc_strdup(mem_ctx, "RAW");
2179         if (!info->default_datatype) {
2180                 return WERR_NOMEM;
2181         }
2182
2183         info->driver_path = talloc_strdup(mem_ctx, "");
2184         info->data_file = talloc_strdup(mem_ctx, "");
2185         info->config_file = talloc_strdup(mem_ctx, "");
2186         info->help_file = talloc_strdup(mem_ctx, "");
2187         if (!info->driver_path || !info->data_file || !info->config_file || !info->help_file) {
2188                 return WERR_NOMEM;
2189         }
2190
2191         return WERR_OK;
2192 }
2193
2194 /****************************************************************************
2195 ****************************************************************************/
2196
2197 static WERROR get_a_printer_driver_3(TALLOC_CTX *mem_ctx,
2198                                      struct spoolss_DriverInfo3 *driver,
2199                                      const char *drivername, const char *arch,
2200                                      uint32_t version)
2201 {
2202         TDB_DATA dbuf;
2203         const char *architecture;
2204         int len = 0;
2205         int i;
2206         char *key = NULL;
2207         fstring name, driverpath, environment, datafile, configfile, helpfile, monitorname, defaultdatatype;
2208
2209         architecture = get_short_archi(arch);
2210         if ( !architecture ) {
2211                 return WERR_UNKNOWN_PRINTER_DRIVER;
2212         }
2213
2214         /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2215
2216         if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2217                 version = 0;
2218
2219         DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2220
2221         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
2222                                 architecture, version, drivername) < 0) {
2223                 return WERR_NOMEM;
2224         }
2225
2226         dbuf = tdb_fetch_bystring(tdb_drivers, key);
2227         if (!dbuf.dptr) {
2228                 SAFE_FREE(key);
2229                 return WERR_UNKNOWN_PRINTER_DRIVER;
2230         }
2231
2232         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2233                           &driver->version,
2234                           name,
2235                           environment,
2236                           driverpath,
2237                           datafile,
2238                           configfile,
2239                           helpfile,
2240                           monitorname,
2241                           defaultdatatype);
2242
2243         driver->driver_name     = talloc_strdup(mem_ctx, name);
2244         driver->architecture    = talloc_strdup(mem_ctx, environment);
2245         driver->driver_path     = talloc_strdup(mem_ctx, driverpath);
2246         driver->data_file       = talloc_strdup(mem_ctx, datafile);
2247         driver->config_file     = talloc_strdup(mem_ctx, configfile);
2248         driver->help_file       = talloc_strdup(mem_ctx, helpfile);
2249         driver->monitor_name    = talloc_strdup(mem_ctx, monitorname);
2250         driver->default_datatype        = talloc_strdup(mem_ctx, defaultdatatype);
2251
2252         i=0;
2253
2254         while (len < dbuf.dsize) {
2255
2256                 fstring file;
2257
2258                 driver->dependent_files = talloc_realloc(mem_ctx, driver->dependent_files, const char *, i+2);
2259                 if (!driver->dependent_files ) {
2260                         DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2261                         break;
2262                 }
2263
2264                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2265                                   &file);
2266
2267                 driver->dependent_files[i] = talloc_strdup(mem_ctx, file);
2268
2269                 i++;
2270         }
2271
2272         if (driver->dependent_files)
2273                 driver->dependent_files[i] = NULL;
2274
2275         SAFE_FREE(dbuf.dptr);
2276         SAFE_FREE(key);
2277
2278         if (len != dbuf.dsize) {
2279                 return get_a_printer_driver_3_default(mem_ctx, driver, drivername, arch);
2280         }
2281
2282         return WERR_OK;
2283 }
2284
2285 /****************************************************************************
2286 ****************************************************************************/
2287 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2288 {
2289         int len = 0;
2290
2291         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2292
2293         if (!nt_devmode)
2294                 return len;
2295
2296         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2297                         nt_devmode->devicename,
2298                         nt_devmode->formname,
2299
2300                         nt_devmode->specversion,
2301                         nt_devmode->driverversion,
2302                         nt_devmode->size,
2303                         nt_devmode->driverextra,
2304                         nt_devmode->orientation,
2305                         nt_devmode->papersize,
2306                         nt_devmode->paperlength,
2307                         nt_devmode->paperwidth,
2308                         nt_devmode->scale,
2309                         nt_devmode->copies,
2310                         nt_devmode->defaultsource,
2311                         nt_devmode->printquality,
2312                         nt_devmode->color,
2313                         nt_devmode->duplex,
2314                         nt_devmode->yresolution,
2315                         nt_devmode->ttoption,
2316                         nt_devmode->collate,
2317                         nt_devmode->logpixels,
2318
2319                         nt_devmode->fields,
2320                         nt_devmode->bitsperpel,
2321                         nt_devmode->pelswidth,
2322                         nt_devmode->pelsheight,
2323                         nt_devmode->displayflags,
2324                         nt_devmode->displayfrequency,
2325                         nt_devmode->icmmethod,
2326                         nt_devmode->icmintent,
2327                         nt_devmode->mediatype,
2328                         nt_devmode->dithertype,
2329                         nt_devmode->reserved1,
2330                         nt_devmode->reserved2,
2331                         nt_devmode->panningwidth,
2332                         nt_devmode->panningheight,
2333                         nt_devmode->nt_dev_private);
2334
2335         if (nt_devmode->nt_dev_private) {
2336                 len += tdb_pack(buf+len, buflen-len, "B",
2337                                 nt_devmode->driverextra,
2338                                 nt_devmode->nt_dev_private);
2339         }
2340
2341         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2342
2343         return len;
2344 }
2345
2346 /****************************************************************************
2347  Pack all values in all printer keys
2348  ***************************************************************************/
2349
2350 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2351 {
2352         int             len = 0;
2353         int             i, j;
2354         struct regval_blob      *val;
2355         struct regval_ctr       *val_ctr;
2356         char *path = NULL;
2357         int             num_values;
2358
2359         if ( !data )
2360                 return 0;
2361
2362         /* loop over all keys */
2363
2364         for ( i=0; i<data->num_keys; i++ ) {
2365                 val_ctr = data->keys[i].values;
2366                 num_values = regval_ctr_numvals( val_ctr );
2367
2368                 /* pack the keyname followed by a empty value */
2369
2370                 len += tdb_pack(buf+len, buflen-len, "pPdB",
2371                                 &data->keys[i].name,
2372                                 data->keys[i].name,
2373                                 REG_NONE,
2374                                 0,
2375                                 NULL);
2376
2377                 /* now loop over all values */
2378
2379                 for ( j=0; j<num_values; j++ ) {
2380                         /* pathname should be stored as <key>\<value> */
2381
2382                         val = regval_ctr_specific_value( val_ctr, j );
2383                         if (asprintf(&path, "%s\\%s",
2384                                         data->keys[i].name,
2385                                         regval_name(val)) < 0) {
2386                                 return -1;
2387                         }
2388
2389                         len += tdb_pack(buf+len, buflen-len, "pPdB",
2390                                         val,
2391                                         path,
2392                                         regval_type(val),
2393                                         regval_size(val),
2394                                         regval_data_p(val) );
2395
2396                         DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2397                         SAFE_FREE(path);
2398                 }
2399
2400         }
2401
2402         /* terminator */
2403
2404         len += tdb_pack(buf+len, buflen-len, "p", NULL);
2405
2406         return len;
2407 }
2408
2409
2410 /****************************************************************************
2411  Delete a printer - this just deletes the printer info file, any open
2412  handles are not affected.
2413 ****************************************************************************/
2414
2415 uint32 del_a_printer(const char *sharename)
2416 {
2417         TDB_DATA kbuf;
2418         char *printdb_path = NULL;
2419         TALLOC_CTX *ctx = talloc_tos();
2420
2421         kbuf = make_printer_tdbkey(ctx, sharename);
2422         tdb_delete(tdb_printers, kbuf);
2423
2424         kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2425         tdb_delete(tdb_printers, kbuf);
2426
2427         close_all_print_db();
2428
2429         if (geteuid() == sec_initial_uid()) {
2430                 if (asprintf(&printdb_path, "%s%s.tdb",
2431                                 cache_path("printing/"),
2432                                 sharename) < 0) {
2433                         return (uint32)-1;
2434                 }
2435                 unlink(printdb_path);
2436                 SAFE_FREE(printdb_path);
2437         }
2438
2439         return 0;
2440 }
2441
2442 /****************************************************************************
2443 ****************************************************************************/
2444 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2445 {
2446         uint8 *buf;
2447         int buflen, len;
2448         int retlen;
2449         WERROR ret;
2450         TDB_DATA kbuf, dbuf;
2451
2452         /*
2453          * in addprinter: no servername and the printer is the name
2454          * in setprinter: servername is \\server
2455          *                and printer is \\server\\printer
2456          *
2457          * Samba manages only local printers.
2458          * we currently don't support things like i
2459          * path=\\other_server\printer
2460          *
2461          * We only store the printername, not \\server\printername
2462          */
2463
2464         if ( info->servername[0] != '\0' ) {
2465                 trim_string(info->printername, info->servername, NULL);
2466                 trim_char(info->printername, '\\', '\0');
2467                 info->servername[0]='\0';
2468         }
2469
2470         /*
2471          * JFM: one day I'll forget.
2472          * below that's info->portname because that's the SAMBA sharename
2473          * and I made NT 'thinks' it's the portname
2474          * the info->sharename is the thing you can name when you add a printer
2475          * that's the short-name when you create shared printer for 95/98
2476          * So I've made a limitation in SAMBA: you can only have 1 printer model
2477          * behind a SAMBA share.
2478          */
2479
2480         buf = NULL;
2481         buflen = 0;
2482
2483  again:
2484         len = 0;
2485         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2486                         info->attributes,
2487                         info->priority,
2488                         info->default_priority,
2489                         info->starttime,
2490                         info->untiltime,
2491                         info->status,
2492                         info->cjobs,
2493                         info->averageppm,
2494                         info->changeid,
2495                         info->c_setprinter,
2496                         info->setuptime,
2497                         info->servername,
2498                         info->printername,
2499                         info->sharename,
2500                         info->portname,
2501                         info->drivername,
2502                         info->comment,
2503                         info->location,
2504                         info->sepfile,
2505                         info->printprocessor,
2506                         info->datatype,
2507                         info->parameters);
2508
2509         len += pack_devicemode(info->devmode, buf+len, buflen-len);
2510         retlen = pack_values( info->data, buf+len, buflen-len );
2511         if (retlen == -1) {
2512                 ret = WERR_NOMEM;
2513                 goto done;
2514         }
2515         len += retlen;
2516
2517         if (buflen != len) {
2518                 buf = (uint8 *)SMB_REALLOC(buf, len);
2519                 if (!buf) {
2520                         DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2521                         ret = WERR_NOMEM;
2522                         goto done;
2523                 }
2524                 buflen = len;
2525                 goto again;
2526         }
2527
2528         kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2529
2530         dbuf.dptr = buf;
2531         dbuf.dsize = len;
2532
2533         ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2534
2535 done:
2536         if (!W_ERROR_IS_OK(ret))
2537                 DEBUG(8, ("error updating printer to tdb on disk\n"));
2538
2539         SAFE_FREE(buf);
2540
2541         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2542                  info->sharename, info->drivername, info->portname, len));
2543
2544         return ret;
2545 }
2546
2547 /****************************************************************************
2548  Create and allocate a default devicemode.
2549 ****************************************************************************/
2550
2551 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
2552                                       const char *devicename,
2553                                       struct spoolss_DeviceMode **devmode)
2554 {
2555         struct spoolss_DeviceMode *dm;
2556         char *dname;
2557
2558         dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2559         if (dm == NULL) {
2560                 return WERR_NOMEM;
2561         }
2562
2563         dname = talloc_asprintf(dm, "%s", devicename);
2564         if (dname == NULL) {
2565                 return WERR_NOMEM;
2566         }
2567         if (strlen(dname) > MAXDEVICENAME) {
2568                 dname[MAXDEVICENAME] = '\0';
2569         }
2570         dm->devicename = dname;
2571
2572         dm->formname = talloc_strdup(dm, "Letter");
2573         if (dm->formname == NULL) {
2574                 return WERR_NOMEM;
2575         }
2576
2577         dm->specversion          = DMSPEC_NT4_AND_ABOVE;
2578         dm->driverversion        = 0x0400;
2579         dm->size                 = 0x00DC;
2580         dm->__driverextra_length = 0;
2581         dm->fields               = DEVMODE_FORMNAME |
2582                                    DEVMODE_TTOPTION |
2583                                    DEVMODE_PRINTQUALITY |
2584                                    DEVMODE_DEFAULTSOURCE |
2585                                    DEVMODE_COPIES |
2586                                    DEVMODE_SCALE |
2587                                    DEVMODE_PAPERSIZE |
2588                                    DEVMODE_ORIENTATION;
2589         dm->orientation          = DMORIENT_PORTRAIT;
2590         dm->papersize            = DMPAPER_LETTER;
2591         dm->paperlength          = 0;
2592         dm->paperwidth           = 0;
2593         dm->scale                = 0x64;
2594         dm->copies               = 1;
2595         dm->defaultsource        = DMBIN_FORMSOURCE;
2596         dm->printquality         = DMRES_HIGH;           /* 0x0258 */
2597         dm->color                = DMRES_MONOCHROME;
2598         dm->duplex               = DMDUP_SIMPLEX;
2599         dm->yresolution          = 0;
2600         dm->ttoption             = DMTT_SUBDEV;
2601         dm->collate              = DMCOLLATE_FALSE;
2602         dm->icmmethod            = 0;
2603         dm->icmintent            = 0;
2604         dm->mediatype            = 0;
2605         dm->dithertype           = 0;
2606
2607         dm->logpixels            = 0;
2608         dm->bitsperpel           = 0;
2609         dm->pelswidth            = 0;
2610         dm->pelsheight           = 0;
2611         dm->displayflags         = 0;
2612         dm->displayfrequency     = 0;
2613         dm->reserved1            = 0;
2614         dm->reserved2            = 0;
2615         dm->panningwidth         = 0;
2616         dm->panningheight        = 0;
2617
2618         dm->driverextra_data.data = NULL;
2619         dm->driverextra_data.length = 0;
2620
2621         *devmode = dm;
2622         return WERR_OK;
2623 }
2624
2625 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
2626                                       struct spoolss_security_descriptor **secdesc)
2627 {
2628         struct security_ace ace[5];     /* max number of ace entries */
2629         int i = 0;
2630         uint32_t sa;
2631         struct security_acl *psa = NULL;
2632         struct security_descriptor *psd = NULL;
2633         DOM_SID adm_sid;
2634         size_t sd_size;
2635
2636         /* Create an ACE where Everyone is allowed to print */
2637
2638         sa = PRINTER_ACE_PRINT;
2639         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2640                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2641
2642         /* Add the domain admins group if we are a DC */
2643
2644         if ( IS_DC ) {
2645                 DOM_SID domadmins_sid;
2646
2647                 sid_compose(&domadmins_sid, get_global_sam_sid(),
2648                             DOMAIN_RID_ADMINS);
2649
2650                 sa = PRINTER_ACE_FULL_CONTROL;
2651                 init_sec_ace(&ace[i++], &domadmins_sid,
2652                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2653                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2654                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2655                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2656         }
2657         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
2658                 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
2659
2660                 sa = PRINTER_ACE_FULL_CONTROL;
2661                 init_sec_ace(&ace[i++], &adm_sid,
2662                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2663                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2664                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2665                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2666         }
2667
2668         /* add BUILTIN\Administrators as FULL CONTROL */
2669
2670         sa = PRINTER_ACE_FULL_CONTROL;
2671         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2672                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2673                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2674         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2675                 SEC_ACE_TYPE_ACCESS_ALLOWED,
2676                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2677
2678         /* Make the security descriptor owned by the BUILTIN\Administrators */
2679
2680         /* The ACL revision number in rpc_secdesc.h differs from the one
2681            created by NT when setting ACE entries in printer
2682            descriptors.  NT4 complains about the property being edited by a
2683            NT5 machine. */
2684
2685         if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
2686                 psd = make_sec_desc(mem_ctx,
2687                                     SD_REVISION,
2688                                     SEC_DESC_SELF_RELATIVE,
2689                                     &global_sid_Builtin_Administrators,
2690                                     &global_sid_Builtin_Administrators,
2691                                     NULL,
2692                                     psa,
2693                                     &sd_size);
2694         }
2695
2696         if (psd == NULL) {
2697                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2698                 return WERR_NOMEM;
2699         }
2700
2701         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2702                  (unsigned int)sd_size));
2703
2704         *secdesc = psd;
2705
2706         return WERR_OK;
2707 }
2708
2709 /****************************************************************************
2710  Malloc and return an NT devicemode.
2711 ****************************************************************************/
2712
2713 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2714 {
2715
2716         char adevice[MAXDEVICENAME];
2717         NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2718
2719         if (nt_devmode == NULL) {
2720                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2721                 return NULL;
2722         }
2723
2724         ZERO_STRUCTP(nt_devmode);
2725
2726         slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2727         fstrcpy(nt_devmode->devicename, adevice);
2728
2729         fstrcpy(nt_devmode->formname, "Letter");
2730
2731         nt_devmode->specversion      = DMSPEC_NT4_AND_ABOVE;
2732         nt_devmode->driverversion    = 0x0400;
2733         nt_devmode->size             = 0x00DC;
2734         nt_devmode->driverextra      = 0x0000;
2735         nt_devmode->fields           = DEVMODE_FORMNAME |
2736                                        DEVMODE_TTOPTION |
2737                                        DEVMODE_PRINTQUALITY |
2738                                        DEVMODE_DEFAULTSOURCE |
2739                                        DEVMODE_COPIES |
2740                                        DEVMODE_SCALE |
2741                                        DEVMODE_PAPERSIZE |
2742                                        DEVMODE_ORIENTATION;
2743         nt_devmode->orientation      = DMORIENT_PORTRAIT;
2744         nt_devmode->papersize        = DMPAPER_LETTER;
2745         nt_devmode->paperlength      = 0;
2746         nt_devmode->paperwidth       = 0;
2747         nt_devmode->scale            = 0x64;
2748         nt_devmode->copies           = 1;
2749         nt_devmode->defaultsource    = DMBIN_FORMSOURCE;
2750         nt_devmode->printquality     = DMRES_HIGH;           /* 0x0258 */
2751         nt_devmode->color            = DMRES_MONOCHROME;
2752         nt_devmode->duplex           = DMDUP_SIMPLEX;
2753         nt_devmode->yresolution      = 0;
2754         nt_devmode->ttoption         = DMTT_SUBDEV;
2755         nt_devmode->collate          = DMCOLLATE_FALSE;
2756         nt_devmode->icmmethod        = 0;
2757         nt_devmode->icmintent        = 0;
2758         nt_devmode->mediatype        = 0;
2759         nt_devmode->dithertype       = 0;
2760
2761         /* non utilisés par un driver d'imprimante */
2762         nt_devmode->logpixels        = 0;
2763         nt_devmode->bitsperpel       = 0;
2764         nt_devmode->pelswidth        = 0;
2765         nt_devmode->pelsheight       = 0;
2766         nt_devmode->displayflags     = 0;
2767         nt_devmode->displayfrequency = 0;
2768         nt_devmode->reserved1        = 0;
2769         nt_devmode->reserved2        = 0;
2770         nt_devmode->panningwidth     = 0;
2771         nt_devmode->panningheight    = 0;
2772
2773         nt_devmode->nt_dev_private = NULL;
2774         return nt_devmode;
2775 }
2776
2777 /****************************************************************************
2778  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2779 ****************************************************************************/
2780
2781 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2782 {
2783         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2784
2785         if(nt_devmode == NULL)
2786                 return;
2787
2788         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2789
2790         SAFE_FREE(nt_devmode->nt_dev_private);
2791         SAFE_FREE(*devmode_ptr);
2792 }
2793
2794 /****************************************************************************
2795  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2796 ****************************************************************************/
2797
2798 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2799 {
2800         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2801
2802         if ( !info )
2803                 return;
2804
2805         free_nt_devicemode(&info->devmode);
2806
2807         TALLOC_FREE( *info_ptr );
2808 }
2809
2810
2811 /****************************************************************************
2812 ****************************************************************************/
2813 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2814 {
2815         int len = 0;
2816         int extra_len = 0;
2817         NT_DEVICEMODE devmode;
2818
2819         ZERO_STRUCT(devmode);
2820
2821         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2822
2823         if (!*nt_devmode) return len;
2824
2825         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2826                           devmode.devicename,
2827                           devmode.formname,
2828
2829                           &devmode.specversion,
2830                           &devmode.driverversion,
2831                           &devmode.size,
2832                           &devmode.driverextra,
2833                           &devmode.orientation,
2834                           &devmode.papersize,
2835                           &devmode.paperlength,
2836                           &devmode.paperwidth,
2837                           &devmode.scale,
2838                           &devmode.copies,
2839                           &devmode.defaultsource,
2840                           &devmode.printquality,
2841                           &devmode.color,
2842                           &devmode.duplex,
2843                           &devmode.yresolution,
2844                           &devmode.ttoption,
2845                           &devmode.collate,
2846                           &devmode.logpixels,
2847
2848                           &devmode.fields,
2849                           &devmode.bitsperpel,
2850                           &devmode.pelswidth,
2851                           &devmode.pelsheight,
2852                           &devmode.displayflags,
2853                           &devmode.displayfrequency,
2854                           &devmode.icmmethod,
2855                           &devmode.icmintent,
2856                           &devmode.mediatype,
2857                           &devmode.dithertype,
2858                           &devmode.reserved1,
2859                           &devmode.reserved2,
2860                           &devmode.panningwidth,
2861                           &devmode.panningheight,
2862                           &devmode.nt_dev_private);
2863
2864         if (devmode.nt_dev_private) {
2865                 /* the len in tdb_unpack is an int value and
2866                  * devmode.driverextra is only a short
2867                  */
2868                 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2869                 devmode.driverextra=(uint16)extra_len;
2870
2871                 /* check to catch an invalid TDB entry so we don't segfault */
2872                 if (devmode.driverextra == 0) {
2873                         devmode.nt_dev_private = NULL;
2874                 }
2875         }
2876
2877         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2878         if (!*nt_devmode) {
2879                 SAFE_FREE(devmode.nt_dev_private);
2880                 return -1;
2881         }
2882
2883         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2884         if (devmode.nt_dev_private)
2885                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2886
2887         return len;
2888 }
2889
2890 /****************************************************************************
2891  Allocate and initialize a new slot.
2892 ***************************************************************************/
2893
2894 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2895 {
2896         NT_PRINTER_KEY  *d;
2897         int             key_index;
2898
2899         if ( !name || !data )
2900                 return -1;
2901
2902         /* allocate another slot in the NT_PRINTER_KEY array */
2903
2904         if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2905                 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2906                 return -1;
2907         }
2908
2909         data->keys = d;
2910
2911         key_index = data->num_keys;
2912
2913         /* initialze new key */
2914
2915         data->keys[key_index].name = talloc_strdup( data, name );
2916
2917         if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, struct regval_ctr )) )
2918                 return -1;
2919
2920         data->num_keys++;
2921
2922         DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2923
2924         return key_index;
2925 }
2926
2927 /****************************************************************************
2928  search for a registry key name in the existing printer data
2929  ***************************************************************************/
2930
2931 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2932 {
2933         int i;
2934
2935         for ( i=0; i<data->num_keys; i++ ) {
2936                 if ( strequal( data->keys[i].name, name ) ) {
2937
2938                         /* cleanup memory */
2939
2940                         TALLOC_FREE( data->keys[i].name );
2941                         TALLOC_FREE( data->keys[i].values );
2942
2943                         /* if not the end of the array, move remaining elements down one slot */
2944
2945                         data->num_keys--;
2946                         if ( data->num_keys && (i < data->num_keys) )
2947                                 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2948
2949                         break;
2950                 }
2951         }
2952
2953
2954         return data->num_keys;
2955 }
2956
2957 /****************************************************************************
2958  search for a registry key name in the existing printer data
2959  ***************************************************************************/
2960
2961 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2962 {
2963         int             key_index = -1;
2964         int             i;
2965
2966         if ( !data || !name )
2967                 return -1;
2968
2969         DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2970
2971         /* loop over all existing keys */
2972
2973         for ( i=0; i<data->num_keys; i++ ) {
2974                 if ( strequal(data->keys[i].name, name) ) {
2975                         DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2976                         key_index = i;
2977                         break;
2978
2979                 }
2980         }
2981
2982         return key_index;
2983 }
2984
2985 /****************************************************************************
2986  ***************************************************************************/
2987
2988 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2989 {
2990         int     i, j;
2991         int     key_len;
2992         int     num_subkeys = 0;
2993         char    *p;
2994         fstring *subkeys_ptr = NULL;
2995         fstring subkeyname;
2996
2997         *subkeys = NULL;
2998
2999         if ( !data )
3000                 return 0;
3001
3002         if ( !key )
3003                 return -1;
3004
3005         /* special case of asking for the top level printer data registry key names */
3006
3007         if ( strlen(key) == 0 ) {
3008                 for ( i=0; i<data->num_keys; i++ ) {
3009
3010                         /* found a match, so allocate space and copy the name */
3011
3012                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3013                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3014                                         num_subkeys+1));
3015                                 return -1;
3016                         }
3017
3018                         fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
3019                         num_subkeys++;
3020                 }
3021
3022                 goto done;
3023         }
3024
3025         /* asking for the subkeys of some key */
3026         /* subkey paths are stored in the key name using '\' as the delimiter */
3027
3028         for ( i=0; i<data->num_keys; i++ ) {
3029                 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
3030
3031                         /* if we found the exact key, then break */
3032                         key_len = strlen( key );
3033                         if ( strlen(data->keys[i].name) == key_len )
3034                                 break;
3035
3036                         /* get subkey path */
3037
3038                         p = data->keys[i].name + key_len;
3039                         if ( *p == '\\' )
3040                                 p++;
3041                         fstrcpy( subkeyname, p );
3042                         if ( (p = strchr( subkeyname, '\\' )) )
3043                                 *p = '\0';
3044
3045                         /* don't add a key more than once */
3046
3047                         for ( j=0; j<num_subkeys; j++ ) {
3048                                 if ( strequal( subkeys_ptr[j], subkeyname ) )
3049                                         break;
3050                         }
3051
3052                         if ( j != num_subkeys )
3053                                 continue;
3054
3055                         /* found a match, so allocate space and copy the name */
3056
3057                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3058                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3059                                         num_subkeys+1));
3060                                 return 0;
3061                         }
3062
3063                         fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
3064                         num_subkeys++;
3065                 }
3066
3067         }
3068
3069         /* return error if the key was not found */
3070
3071         if ( i == data->num_keys ) {
3072                 SAFE_FREE(subkeys_ptr);
3073                 return -1;
3074         }
3075
3076 done:
3077         /* tag off the end */
3078
3079         if (num_subkeys)
3080                 fstrcpy(subkeys_ptr[num_subkeys], "" );
3081
3082         *subkeys = subkeys_ptr;
3083
3084         return num_subkeys;
3085 }
3086
3087 #ifdef HAVE_ADS
3088 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3089                             const char *sz)
3090 {
3091         regval_ctr_delvalue(ctr, val_name);
3092         regval_ctr_addvalue_sz(ctr, val_name, sz);
3093 }
3094
3095 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
3096                                uint32 dword)
3097 {
3098         regval_ctr_delvalue(ctr, val_name);
3099         regval_ctr_addvalue(ctr, val_name, REG_DWORD,
3100                             (char *) &dword, sizeof(dword));
3101 }
3102
3103 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
3104                               bool b)
3105 {
3106         uint8 bin_bool = (b ? 1 : 0);
3107         regval_ctr_delvalue(ctr, val_name);
3108         regval_ctr_addvalue(ctr, val_name, REG_BINARY,
3109                             (char *) &bin_bool, sizeof(bin_bool));
3110 }
3111
3112 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3113                                          const char *multi_sz)
3114 {
3115         const char *a[2];
3116
3117         a[0] = multi_sz;
3118         a[1] = NULL;
3119
3120         regval_ctr_delvalue(ctr, val_name);
3121         regval_ctr_addvalue_multi_sz(ctr, val_name, a);
3122 }
3123
3124 /****************************************************************************
3125  * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3126  *
3127  * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3128  * @return bool indicating success or failure
3129  ***************************************************************************/
3130
3131 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
3132 {
3133         struct regval_ctr *ctr = NULL;
3134         fstring longname;
3135         const char *dnssuffix;
3136         char *allocated_string = NULL;
3137         const char *ascii_str;
3138         int i;
3139
3140         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3141                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3142         ctr = info2->data->keys[i].values;
3143
3144         map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3145         map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3146
3147         /* we make the assumption that the netbios name is the same
3148            as the DNS name sinc ethe former will be what we used to
3149            join the domain */
3150
3151         dnssuffix = get_mydnsdomname(talloc_tos());
3152         if (dnssuffix && *dnssuffix) {
3153                 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3154         } else {
3155                 fstrcpy( longname, global_myname() );
3156         }
3157
3158         map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3159
3160         if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3161                 return false;
3162         }
3163         map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3164         SAFE_FREE(allocated_string);
3165
3166         map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3167         map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3168         map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3169         map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3170         map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3171         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3172         map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3173         map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3174         map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3175
3176         map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3177                           (info2->attributes &
3178                            PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3179
3180         switch (info2->attributes & 0x3) {
3181         case 0:
3182                 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3183                 break;
3184         case 1:
3185                 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3186                 break;
3187         case 2:
3188                 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3189                 break;
3190         default:
3191                 ascii_str = "unknown";
3192         }
3193         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3194
3195         return True;
3196 }
3197
3198 /*****************************************************************
3199  ****************************************************************/
3200
3201 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3202                                struct GUID guid)
3203 {
3204         int i;
3205         struct regval_ctr *ctr=NULL;
3206
3207         /* find the DsSpooler key */
3208         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3209                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3210         ctr = info2->data->keys[i].values;
3211
3212         regval_ctr_delvalue(ctr, "objectGUID");
3213
3214         /* We used to store this as a REG_BINARY but that causes
3215            Vista to whine */
3216
3217         regval_ctr_addvalue_sz(ctr, "objectGUID",
3218                                GUID_string(talloc_tos(), &guid));
3219 }
3220
3221 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3222                                      NT_PRINTER_INFO_LEVEL *printer)
3223 {
3224         ADS_STATUS ads_rc;
3225         LDAPMessage *res;
3226         char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3227         char *srv_dn_utf8, **srv_cn_utf8;
3228         TALLOC_CTX *ctx;
3229         ADS_MODLIST mods;
3230         const char *attrs[] = {"objectGUID", NULL};
3231         struct GUID guid;
3232         WERROR win_rc = WERR_OK;
3233         size_t converted_size;
3234
3235         /* build the ads mods */
3236         ctx = talloc_init("nt_printer_publish_ads");
3237         if (ctx == NULL) {
3238                 return WERR_NOMEM;
3239         }
3240
3241         DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3242
3243         /* figure out where to publish */
3244         ads_find_machine_acct(ads, &res, global_myname());
3245
3246         /* We use ldap_get_dn here as we need the answer
3247          * in utf8 to call ldap_explode_dn(). JRA. */
3248
3249         srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3250         if (!srv_dn_utf8) {
3251                 TALLOC_FREE(ctx);
3252                 return WERR_SERVER_UNAVAILABLE;
3253         }
3254         ads_msgfree(ads, res);
3255         srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3256         if (!srv_cn_utf8) {
3257                 TALLOC_FREE(ctx);
3258                 ldap_memfree(srv_dn_utf8);
3259                 return WERR_SERVER_UNAVAILABLE;
3260         }
3261         /* Now convert to CH_UNIX. */
3262         if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3263                 TALLOC_FREE(ctx);
3264                 ldap_memfree(srv_dn_utf8);
3265                 ldap_memfree(srv_cn_utf8);
3266                 return WERR_SERVER_UNAVAILABLE;
3267         }
3268         if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3269                 TALLOC_FREE(ctx);
3270                 ldap_memfree(srv_dn_utf8);
3271                 ldap_memfree(srv_cn_utf8);
3272                 TALLOC_FREE(srv_dn);
3273                 return WERR_SERVER_UNAVAILABLE;
3274         }
3275
3276         ldap_memfree(srv_dn_utf8);
3277         ldap_memfree(srv_cn_utf8);
3278
3279         srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3280         if (!srv_cn_escaped) {
3281                 TALLOC_FREE(ctx);
3282                 return WERR_SERVER_UNAVAILABLE;
3283         }
3284         sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3285         if (!sharename_escaped) {
3286                 SAFE_FREE(srv_cn_escaped);
3287                 TALLOC_FREE(ctx);
3288                 return WERR_SERVER_UNAVAILABLE;
3289         }
3290
3291         prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3292
3293         SAFE_FREE(srv_cn_escaped);
3294         SAFE_FREE(sharename_escaped);
3295
3296         mods = ads_init_mods(ctx);
3297
3298         if (mods == NULL) {
3299                 SAFE_FREE(prt_dn);
3300                 TALLOC_FREE(ctx);
3301                 return WERR_NOMEM;
3302         }
3303
3304         get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3305         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3306                     printer->info_2->sharename);
3307
3308         /* publish it */
3309         ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3310         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3311                 int i;
3312                 for (i=0; mods[i] != 0; i++)
3313                         ;
3314                 mods[i] = (LDAPMod *)-1;
3315                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3316         }
3317
3318         if (!ADS_ERR_OK(ads_rc))
3319                 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3320
3321         /* retreive the guid and store it locally */
3322         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3323                 ZERO_STRUCT(guid);
3324                 ads_pull_guid(ads, res, &guid);
3325                 ads_msgfree(ads, res);
3326                 store_printer_guid(printer->info_2, guid);
3327                 win_rc = mod_a_printer(printer, 2);
3328         }
3329         TALLOC_FREE(ctx);
3330
3331         return win_rc;
3332 }
3333
3334 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3335                                        NT_PRINTER_INFO_LEVEL *printer)
3336 {
3337         ADS_STATUS ads_rc;
3338         LDAPMessage *res = NULL;
3339         char *prt_dn = NULL;
3340
3341         DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3342
3343         /* remove the printer from the directory */
3344         ads_rc = ads_find_printer_on_server(ads, &res,
3345                             printer->info_2->sharename, global_myname());
3346
3347         if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3348                 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3349                 if (!prt_dn) {
3350                         ads_msgfree(ads, res);
3351                         return WERR_NOMEM;
3352                 }
3353                 ads_rc = ads_del_dn(ads, prt_dn);
3354                 TALLOC_FREE(prt_dn);
3355         }
3356
3357         if (res) {
3358                 ads_msgfree(ads, res);
3359         }
3360         return WERR_OK;
3361 }
3362
3363 /****************************************************************************
3364  * Publish a printer in the directory
3365  *
3366  * @param snum describing printer service
3367  * @return WERROR indicating status of publishing
3368  ***************************************************************************/
3369
3370 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3371 {
3372         ADS_STATUS ads_rc;
3373         ADS_STRUCT *ads = NULL;
3374         NT_PRINTER_INFO_LEVEL *printer = NULL;
3375         WERROR win_rc;
3376
3377         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3378         if (!W_ERROR_IS_OK(win_rc))
3379                 goto done;
3380
3381         switch (action) {
3382         case DSPRINT_PUBLISH:
3383         case DSPRINT_UPDATE:
3384                 /* set the DsSpooler info and attributes */
3385                 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3386                         win_rc = WERR_NOMEM;
3387                         goto done;
3388                 }
3389
3390                 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3391                 break;
3392         case DSPRINT_UNPUBLISH:
3393                 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3394                 break;
3395         default:
3396                 win_rc = WERR_NOT_SUPPORTED;
3397                 goto done;
3398         }
3399
3400         win_rc = mod_a_printer(printer, 2);
3401         if (!W_ERROR_IS_OK(win_rc)) {
3402                 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3403                 goto done;
3404         }
3405
3406         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3407         if (!ads) {
3408                 DEBUG(3, ("ads_init() failed\n"));
3409                 win_rc = WERR_SERVER_UNAVAILABLE;
3410                 goto done;
3411         }
3412         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3413         SAFE_FREE(ads->auth.password);
3414         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3415                 NULL, NULL);
3416
3417         /* ads_connect() will find the DC for us */
3418         ads_rc = ads_connect(ads);
3419         if (!ADS_ERR_OK(ads_rc)) {
3420                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3421                 win_rc = WERR_ACCESS_DENIED;
3422                 goto done;
3423         }
3424
3425         switch (action) {
3426         case DSPRINT_PUBLISH:
3427         case DSPRINT_UPDATE:
3428                 win_rc = nt_printer_publish_ads(ads, printer);
3429                 break;
3430         case DSPRINT_UNPUBLISH:
3431                 win_rc = nt_printer_unpublish_ads(ads, printer);
3432                 break;
3433         }
3434
3435 done:
3436         free_a_printer(&printer, 2);
3437         ads_destroy(&ads);
3438         return win_rc;
3439 }
3440
3441 WERROR check_published_printers(void)
3442 {
3443         ADS_STATUS ads_rc;
3444         ADS_STRUCT *ads = NULL;
3445         int snum;
3446         int n_services = lp_numservices();
3447         NT_PRINTER_INFO_LEVEL *printer = NULL;
3448
3449         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3450         if (!ads) {
3451                 DEBUG(3, ("ads_init() failed\n"));
3452                 return WERR_SERVER_UNAVAILABLE;
3453         }
3454         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3455         SAFE_FREE(ads->auth.password);
3456         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3457                 NULL, NULL);
3458
3459         /* ads_connect() will find the DC for us */
3460         ads_rc = ads_connect(ads);
3461         if (!ADS_ERR_OK(ads_rc)) {
3462                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3463                 ads_destroy(&ads);
3464                 ads_kdestroy("MEMORY:prtpub_cache");
3465                 return WERR_ACCESS_DENIED;
3466         }
3467
3468         for (snum = 0; snum < n_services; snum++) {
3469                 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3470                         continue;
3471
3472                 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3473                                                 lp_servicename(snum))) &&
3474                     (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3475                         nt_printer_publish_ads(ads, printer);
3476
3477                 free_a_printer(&printer, 2);
3478         }
3479
3480         ads_destroy(&ads);
3481         ads_kdestroy("MEMORY:prtpub_cache");
3482         return WERR_OK;
3483 }
3484
3485 bool is_printer_published(Printer_entry *print_hnd, int snum,
3486                           struct GUID *guid)
3487 {
3488         NT_PRINTER_INFO_LEVEL *printer = NULL;
3489         struct regval_ctr *ctr;
3490         struct regval_blob *guid_val;
3491         WERROR win_rc;
3492         int i;
3493         bool ret = False;
3494         DATA_BLOB blob;
3495
3496         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3497
3498         if (!W_ERROR_IS_OK(win_rc) ||
3499             !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3500             ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3501             !(ctr = printer->info_2->data->keys[i].values) ||
3502             !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3503         {
3504                 free_a_printer(&printer, 2);
3505                 return False;
3506         }
3507
3508         /* fetching printer guids really ought to be a separate function. */
3509
3510         if ( guid ) {
3511                 char *guid_str;
3512
3513                 /* We used to store the guid as REG_BINARY, then swapped
3514                    to REG_SZ for Vista compatibility so check for both */
3515
3516                 switch ( regval_type(guid_val) ){
3517                 case REG_SZ:
3518                         blob = data_blob_const(regval_data_p(guid_val),
3519                                                regval_size(guid_val));
3520                         pull_reg_sz(talloc_tos(), &blob, (const char **)&guid_str);
3521                         ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3522                         talloc_free(guid_str);
3523                         break;
3524                 case REG_BINARY:
3525                         if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3526                                 ret = False;
3527                                 break;
3528                         }
3529                         memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3530                         break;
3531                 default:
3532                         DEBUG(0,("is_printer_published: GUID value stored as "
3533                                  "invaluid type (%d)\n", regval_type(guid_val) ));
3534                         break;
3535                 }
3536         }
3537
3538         free_a_printer(&printer, 2);
3539         return ret;
3540 }
3541 #else
3542 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3543 {
3544         return WERR_OK;
3545 }
3546
3547 WERROR check_published_printers(void)
3548 {
3549         return WERR_OK;
3550 }
3551
3552 bool is_printer_published(Printer_entry *print_hnd, int snum,
3553                           struct GUID *guid)
3554 {
3555         return False;
3556 }
3557 #endif /* HAVE_ADS */
3558
3559 /****************************************************************************
3560  ***************************************************************************/
3561
3562 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3563 {
3564         NT_PRINTER_DATA *data;
3565         int             i;
3566         int             removed_keys = 0;
3567         int             empty_slot;
3568
3569         data = p2->data;
3570         empty_slot = data->num_keys;
3571
3572         if ( !key )
3573                 return WERR_INVALID_PARAM;
3574
3575         /* remove all keys */
3576
3577         if ( !strlen(key) ) {
3578
3579                 TALLOC_FREE( data );
3580
3581                 p2->data = NULL;
3582
3583                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3584                         p2->printername ));
3585
3586                 return WERR_OK;
3587         }
3588
3589         /* remove a specific key (and all subkeys) */
3590
3591         for ( i=0; i<data->num_keys; i++ ) {
3592                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3593                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3594                                 data->keys[i].name));
3595
3596                         TALLOC_FREE( data->keys[i].name );
3597                         TALLOC_FREE( data->keys[i].values );
3598
3599                         /* mark the slot as empty */
3600
3601                         ZERO_STRUCTP( &data->keys[i] );
3602                 }
3603         }
3604
3605         /* find the first empty slot */
3606
3607         for ( i=0; i<data->num_keys; i++ ) {
3608                 if ( !data->keys[i].name ) {
3609                         empty_slot = i;
3610                         removed_keys++;
3611                         break;
3612                 }
3613         }
3614
3615         if ( i == data->num_keys )
3616                 /* nothing was removed */
3617                 return WERR_INVALID_PARAM;
3618
3619         /* move everything down */
3620
3621         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3622                 if ( data->keys[i].name ) {
3623                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3624                         ZERO_STRUCTP( &data->keys[i] );
3625                         empty_slot++;
3626                         removed_keys++;
3627                 }
3628         }
3629
3630         /* update count */
3631
3632         data->num_keys -= removed_keys;
3633
3634         /* sanity check to see if anything is left */
3635
3636         if ( !data->num_keys ) {
3637                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3638
3639                 SAFE_FREE( data->keys );
3640                 ZERO_STRUCTP( data );
3641         }
3642
3643         return WERR_OK;
3644 }
3645
3646 /****************************************************************************
3647  ***************************************************************************/
3648
3649 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3650 {
3651         WERROR          result = WERR_OK;
3652         int             key_index;
3653
3654         /* we must have names on non-zero length */
3655
3656         if ( !key || !*key|| !value || !*value )
3657                 return WERR_INVALID_NAME;
3658
3659         /* find the printer key first */
3660
3661         key_index = lookup_printerkey( p2->data, key );
3662         if ( key_index == -1 )
3663                 return WERR_OK;
3664
3665         /* make sure the value exists so we can return the correct error code */
3666
3667         if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3668                 return WERR_BADFILE;
3669
3670         regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3671
3672         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3673                 key, value ));
3674
3675         return result;
3676 }
3677
3678 /****************************************************************************
3679  ***************************************************************************/
3680
3681 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3682                            uint32 type, uint8 *data, int real_len )
3683 {
3684         WERROR          result = WERR_OK;
3685         int             key_index;
3686
3687         /* we must have names on non-zero length */
3688
3689         if ( !key || !*key|| !value || !*value )
3690                 return WERR_INVALID_NAME;
3691
3692         /* find the printer key first */
3693
3694         key_index = lookup_printerkey( p2->data, key );
3695         if ( key_index == -1 )
3696                 key_index = add_new_printer_key( p2->data, key );
3697
3698         if ( key_index == -1 )
3699                 return WERR_NOMEM;
3700
3701         regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3702                 type, (const char *)data, real_len );
3703
3704         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3705                 key, value, type, real_len  ));
3706
3707         return result;
3708 }
3709
3710 /****************************************************************************
3711  ***************************************************************************/
3712
3713 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3714 {
3715         int             key_index;
3716
3717         if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3718                 return NULL;
3719
3720         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3721                 key, value ));
3722
3723         return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3724 }
3725
3726 /****************************************************************************
3727  Unpack a list of registry values frem the TDB
3728  ***************************************************************************/
3729
3730 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3731 {
3732         int             len = 0;
3733         uint32          type;
3734         fstring string;
3735         const char *valuename = NULL;
3736         const char *keyname = NULL;
3737         char            *str;
3738         int             size;
3739         uint8           *data_p;
3740         struct regval_blob      *regval_p;
3741         int             key_index;
3742
3743         /* add the "PrinterDriverData" key first for performance reasons */
3744
3745         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3746
3747         /* loop and unpack the rest of the registry values */
3748
3749         while ( True ) {
3750
3751                 /* check to see if there are any more registry values */
3752
3753                 regval_p = NULL;
3754                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3755                 if ( !regval_p )
3756                         break;
3757
3758                 /* unpack the next regval */
3759
3760                 len += tdb_unpack(buf+len, buflen-len, "fdB",
3761                                   string,
3762                                   &type,
3763                                   &size,
3764                                   &data_p);
3765
3766                 /* lookup for subkey names which have a type of REG_NONE */
3767                 /* there's no data with this entry */
3768
3769                 if ( type == REG_NONE ) {
3770                         if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3771                                 add_new_printer_key( printer_data, string );
3772                         continue;
3773                 }
3774
3775                 /*
3776                  * break of the keyname from the value name.
3777                  * Valuenames can have embedded '\'s so be careful.
3778                  * only support one level of keys.  See the
3779                  * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3780                  * -- jerry
3781                  */
3782
3783                 str = strchr_m( string, '\\');
3784
3785                 /* Put in "PrinterDriverData" is no key specified */
3786
3787                 if ( !str ) {
3788                         keyname = SPOOL_PRINTERDATA_KEY;
3789                         valuename = string;
3790                 }
3791                 else {
3792                         *str = '\0';
3793                         keyname = string;
3794                         valuename = str+1;
3795                 }
3796
3797                 /* see if we need a new key */
3798
3799                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3800                         key_index = add_new_printer_key( printer_data, keyname );
3801
3802                 if ( key_index == -1 ) {
3803                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3804                                 keyname));
3805                         break;
3806                 }
3807
3808                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3809
3810                 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3811                    Thanks to Martin Zielinski for the hint. */
3812
3813                 if ( type == REG_BINARY &&
3814                      strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3815                      strequal( valuename, "objectGUID" ) )
3816                 {
3817                         struct GUID guid;
3818
3819                         /* convert the GUID to a UNICODE string */
3820
3821                         memcpy( &guid, data_p, sizeof(struct GUID) );
3822
3823                         regval_ctr_addvalue_sz(printer_data->keys[key_index].values,
3824                                                valuename,
3825                                                GUID_string(talloc_tos(), &guid));
3826
3827                 } else {
3828                         /* add the value */
3829
3830                         regval_ctr_addvalue( printer_data->keys[key_index].values,
3831                                              valuename, type, (const char *)data_p,
3832                                              size );
3833                 }
3834
3835                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3836
3837         }
3838
3839         return len;
3840 }
3841
3842 /****************************************************************************
3843  ***************************************************************************/
3844
3845 static char *win_driver;
3846 static char *os2_driver;
3847
3848 static const char *get_win_driver(void)
3849 {
3850         if (win_driver == NULL) {
3851                 return "";
3852         }
3853         return win_driver;
3854 }
3855
3856 static const char *get_os2_driver(void)
3857 {
3858         if (os2_driver == NULL) {
3859                 return "";
3860         }
3861         return os2_driver;
3862 }
3863
3864 static bool set_driver_mapping(const char *from, const char *to)
3865 {
3866         SAFE_FREE(win_driver);
3867         SAFE_FREE(os2_driver);
3868
3869         win_driver = SMB_STRDUP(from);
3870         os2_driver = SMB_STRDUP(to);
3871
3872         if (win_driver == NULL || os2_driver == NULL) {
3873                 SAFE_FREE(win_driver);
3874                 SAFE_FREE(os2_driver);
3875                 return false;
3876         }
3877         return true;
3878 }
3879
3880 static void map_to_os2_driver(fstring drivername)
3881 {
3882         char *mapfile = lp_os2_driver_map();
3883         char **lines = NULL;
3884         int numlines = 0;
3885         int i;
3886
3887         if (!strlen(drivername))
3888                 return;
3889
3890         if (!*mapfile)
3891                 return;
3892
3893         if (strequal(drivername, get_win_driver())) {
3894                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3895                         drivername, get_os2_driver()));
3896                 fstrcpy(drivername, get_os2_driver());
3897                 return;
3898         }
3899
3900         lines = file_lines_load(mapfile, &numlines,0,NULL);
3901         if (numlines == 0 || lines == NULL) {
3902                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3903                 TALLOC_FREE(lines);
3904                 return;
3905         }
3906
3907         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3908
3909         for( i = 0; i < numlines; i++) {
3910                 char *nt_name = lines[i];
3911                 char *os2_name = strchr(nt_name,'=');
3912
3913                 if (!os2_name)
3914                         continue;
3915
3916                 *os2_name++ = 0;
3917
3918                 while (isspace(*nt_name))
3919                         nt_name++;
3920
3921                 if (!*nt_name || strchr("#;",*nt_name))
3922                         continue;
3923
3924                 {
3925                         int l = strlen(nt_name);
3926                         while (l && isspace(nt_name[l-1])) {
3927                                 nt_name[l-1] = 0;
3928                                 l--;
3929                         }
3930                 }
3931
3932                 while (isspace(*os2_name))
3933                         os2_name++;
3934
3935                 {
3936                         int l = strlen(os2_name);
3937                         while (l && isspace(os2_name[l-1])) {
3938                                 os2_name[l-1] = 0;
3939                                 l--;
3940                         }
3941                 }
3942
3943                 if (strequal(nt_name,drivername)) {
3944                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3945                         set_driver_mapping(drivername,os2_name);
3946                         fstrcpy(drivername,os2_name);
3947                         TALLOC_FREE(lines);
3948                         return;
3949                 }
3950         }
3951
3952         TALLOC_FREE(lines);
3953 }
3954
3955 /**
3956  * @internal
3957  *
3958  * @brief Map a Windows driver to a OS/2 driver.
3959  *
3960  * @param[in]  mem_ctx  The memory context to use.
3961  *
3962  * @param[in,out] pdrivername The drivername of Windows to remap.
3963  *
3964  * @return              WERR_OK on success, a corresponding WERROR on failure.
3965  */
3966 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
3967 {
3968         const char *mapfile = lp_os2_driver_map();
3969         char **lines = NULL;
3970         const char *drivername;
3971         int numlines = 0;
3972         int i;
3973
3974         if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
3975                 return WERR_INVALID_PARAMETER;
3976         }
3977
3978         drivername = *pdrivername;
3979
3980         if (mapfile[0] == '\0') {
3981                 return WERR_BADFILE;
3982         }
3983
3984         if (strequal(drivername, get_win_driver())) {
3985                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3986                         drivername, get_os2_driver()));
3987                 drivername = talloc_strdup(mem_ctx, get_os2_driver());
3988                 if (drivername == NULL) {
3989                         return WERR_NOMEM;
3990                 }
3991                 *pdrivername = drivername;
3992                 return WERR_OK;
3993         }
3994
3995         lines = file_lines_load(mapfile, &numlines, 0, NULL);
3996         if (numlines == 0 || lines == NULL) {
3997                 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
3998                 TALLOC_FREE(lines);
3999                 return WERR_EMPTY;
4000         }
4001
4002         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
4003
4004         for( i = 0; i < numlines; i++) {
4005                 char *nt_name = lines[i];
4006                 char *os2_name = strchr(nt_name, '=');
4007
4008                 if (os2_name == NULL) {
4009                         continue;
4010                 }
4011
4012                 *os2_name++ = '\0';
4013
4014                 while (isspace(*nt_name)) {
4015                         nt_name++;
4016                 }
4017
4018                 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
4019                         continue;
4020                 }
4021
4022                 {
4023                         int l = strlen(nt_name);
4024                         while (l && isspace(nt_name[l - 1])) {
4025                                 nt_name[l - 1] = 0;
4026                                 l--;
4027                         }
4028                 }
4029
4030                 while (isspace(*os2_name)) {
4031                         os2_name++;
4032                 }
4033
4034                 {
4035                         int l = strlen(os2_name);
4036                         while (l && isspace(os2_name[l-1])) {
4037                                 os2_name[l-1] = 0;
4038                                 l--;
4039                         }
4040                 }
4041
4042                 if (strequal(nt_name, drivername)) {
4043                         DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
4044                         set_driver_mapping(drivername, os2_name);
4045                         drivername = talloc_strdup(mem_ctx, os2_name);
4046                         TALLOC_FREE(lines);
4047                         if (drivername == NULL) {
4048                                 return WERR_NOMEM;
4049                         }
4050                         *pdrivername = drivername;
4051                         return WERR_OK;
4052                 }
4053         }
4054
4055         TALLOC_FREE(lines);
4056         return WERR_OK;
4057 }
4058
4059 /****************************************************************************
4060  Get a default printer info 2 struct.
4061 ****************************************************************************/
4062
4063 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
4064                                 const char *servername,
4065                                 const char* sharename,
4066                                 bool get_loc_com)
4067 {
4068         int snum = lp_servicenumber(sharename);
4069
4070         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4071         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4072                 servername, sharename);
4073         fstrcpy(info->sharename, sharename);
4074         fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
4075
4076         /* by setting the driver name to an empty string, a local NT admin
4077            can now run the **local** APW to install a local printer driver
4078            for a Samba shared printer in 2.2.  Without this, drivers **must** be
4079            installed on the Samba server for NT clients --jerry */
4080 #if 0   /* JERRY --do not uncomment-- */
4081         if (!*info->drivername)
4082                 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
4083 #endif
4084
4085
4086         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
4087
4088         strlcpy(info->comment, "", sizeof(info->comment));
4089         fstrcpy(info->printprocessor, "winprint");
4090         fstrcpy(info->datatype, "RAW");
4091
4092 #ifdef HAVE_CUPS
4093         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4094                 /* Pull the location and comment strings from cups if we don't
4095                    already have one */
4096                 if ( !strlen(info->location) || !strlen(info->comment) ) {
4097                         char *comment = NULL;
4098                         char *location = NULL;
4099                         if (cups_pull_comment_location(info, info->sharename,
4100                                                        &comment, &location)) {
4101                                 strlcpy(info->comment, comment, sizeof(info->comment));
4102                                 fstrcpy(info->location, location);
4103                                 TALLOC_FREE(comment);
4104                                 TALLOC_FREE(location);
4105                         }
4106                 }
4107         }
4108 #endif
4109
4110         info->attributes = PRINTER_ATTRIBUTE_SAMBA;
4111
4112         info->starttime = 0; /* Minutes since 12:00am GMT */
4113         info->untiltime = 0; /* Minutes since 12:00am GMT */
4114         info->priority = 1;
4115         info->default_priority = 1;
4116         info->setuptime = (uint32)time(NULL);
4117
4118         /*
4119          * I changed this as I think it is better to have a generic
4120          * DEVMODE than to crash Win2k explorer.exe   --jerry
4121          * See the HP Deskjet 990c Win2k drivers for an example.
4122          *
4123          * However the default devmode appears to cause problems
4124          * with the HP CLJ 8500 PCL driver.  Hence the addition of
4125          * the "default devmode" parameter   --jerry 22/01/2002
4126          */
4127
4128         if (lp_default_devmode(snum)) {
4129                 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
4130                         goto fail;
4131                 }
4132         } else {
4133                 info->devmode = NULL;
4134         }
4135
4136         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4137                 goto fail;
4138         }
4139
4140         info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
4141         if (!info->data) {
4142                 goto fail;
4143         }
4144
4145         add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
4146
4147         return WERR_OK;
4148
4149 fail:
4150         if (info->devmode)
4151                 free_nt_devicemode(&info->devmode);
4152
4153         return WERR_ACCESS_DENIED;
4154 }
4155
4156 /****************************************************************************
4157 ****************************************************************************/
4158
4159 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
4160                                 const char *servername,
4161                                 const char *sharename,
4162                                 bool get_loc_com)
4163 {
4164         int len = 0;
4165         int snum = lp_servicenumber(sharename);
4166         TDB_DATA kbuf, dbuf;
4167         fstring printername;
4168         char adevice[MAXDEVICENAME];
4169         char *comment = NULL;
4170
4171         kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4172
4173         dbuf = tdb_fetch(tdb_printers, kbuf);
4174         if (!dbuf.dptr) {
4175                 return get_a_printer_2_default(info, servername,
4176                                         sharename, get_loc_com);
4177         }
4178
4179         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4180                         &info->attributes,
4181                         &info->priority,
4182                         &info->default_priority,
4183                         &info->starttime,
4184                         &info->untiltime,
4185                         &info->status,
4186                         &info->cjobs,
4187                         &info->averageppm,
4188                         &info->changeid,
4189                         &info->c_setprinter,
4190                         &info->setuptime,
4191                         info->servername,
4192                         info->printername,
4193                         info->sharename,
4194                         info->portname,
4195                         info->drivername,
4196                         &comment,
4197                         info->location,
4198                         info->sepfile,
4199                         info->printprocessor,
4200                         info->datatype,
4201                         info->parameters);
4202
4203         if (comment) {
4204                 strlcpy(info->comment, comment, sizeof(info->comment));
4205                 SAFE_FREE(comment);
4206         }
4207
4208         /* Samba has to have shared raw drivers. */
4209         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4210         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4211
4212         /* Restore the stripped strings. */
4213         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4214
4215         if ( lp_force_printername(snum) ) {
4216                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4217         } else {
4218                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4219         }
4220
4221         fstrcpy(info->printername, printername);
4222
4223 #ifdef HAVE_CUPS
4224         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4225                 /* Pull the location and comment strings from cups if we don't
4226                    already have one */
4227                 if ( !strlen(info->location) || !strlen(info->comment) ) {
4228                         char *location = NULL;
4229                         comment = NULL;
4230                         if (cups_pull_comment_location(info, info->sharename,
4231                                                        &comment, &location)) {
4232                                 strlcpy(info->comment, comment, sizeof(info->comment));
4233                                 fstrcpy(info->location, location);
4234                                 TALLOC_FREE(comment);
4235                                 TALLOC_FREE(location);
4236                         }
4237                 }
4238         }
4239 #endif
4240
4241         len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4242
4243         /*
4244          * Some client drivers freak out if there is a NULL devmode
4245          * (probably the driver is not checking before accessing
4246          * the devmode pointer)   --jerry
4247          *
4248          * See comments in get_a_printer_2_default()
4249          */
4250
4251         if (lp_default_devmode(snum) && !info->devmode) {
4252                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4253                         printername));
4254                 info->devmode = construct_nt_devicemode(printername);
4255         }
4256
4257         slprintf( adevice, sizeof(adevice), "%s", info->printername );
4258         if (info->devmode) {
4259                 fstrcpy(info->devmode->devicename, adevice);
4260         }
4261
4262         if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4263                 DEBUG(0,("unpack_values: talloc() failed!\n"));
4264                 SAFE_FREE(dbuf.dptr);
4265                 return WERR_NOMEM;
4266         }
4267         len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4268
4269         /* This will get the current RPC talloc context, but we should be
4270            passing this as a parameter... fixme... JRA ! */
4271
4272         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4273                 SAFE_FREE(dbuf.dptr);
4274                 return WERR_NOMEM;
4275         }
4276
4277         /* Fix for OS/2 drivers. */
4278
4279         if (get_remote_arch() == RA_OS2) {
4280                 map_to_os2_driver(info->drivername);
4281         }
4282
4283         SAFE_FREE(dbuf.dptr);
4284
4285         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4286                  sharename, info->printername, info->drivername));
4287
4288         return WERR_OK;
4289 }
4290
4291 /****************************************************************************
4292  Debugging function, dump at level 6 the struct in the logs.
4293 ****************************************************************************/
4294 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4295 {
4296         uint32 result;
4297         NT_PRINTER_INFO_LEVEL_2 *info2;
4298
4299         DEBUG(106,("Dumping printer at level [%d]\n", level));
4300
4301         switch (level) {
4302                 case 2:
4303                 {
4304                         if (printer->info_2 == NULL)
4305                                 result=5;
4306                         else
4307                         {
4308                                 info2=printer->info_2;
4309
4310                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4311                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4312                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4313                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4314                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4315                                 DEBUGADD(106,("status:[%d]\n", info2->status));
4316                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4317                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4318                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4319                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4320                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4321
4322                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4323                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4324                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4325                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4326                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4327                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4328                                 DEBUGADD(106,("location:[%s]\n", info2->location));
4329                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4330                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4331                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4332                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4333                                 result=0;
4334                         }
4335                         break;
4336                 }
4337                 default:
4338                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4339                         result=1;
4340                         break;
4341         }
4342
4343         return result;
4344 }
4345
4346 /****************************************************************************
4347  Update the changeid time.
4348  This is SO NASTY as some drivers need this to change, others need it
4349  static. This value will change every second, and I must hope that this
4350  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4351  UTAH ! JRA.
4352 ****************************************************************************/
4353
4354 static uint32 rev_changeid(void)
4355 {
4356         struct timeval tv;
4357
4358         get_process_uptime(&tv);
4359
4360 #if 1   /* JERRY */
4361         /* Return changeid as msec since spooler restart */
4362         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4363 #else
4364         /*
4365          * This setting seems to work well but is too untested
4366          * to replace the above calculation.  Left in for experiementation
4367          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
4368          */
4369         return tv.tv_sec * 10 + tv.tv_usec / 100000;
4370 #endif
4371 }
4372
4373
4374 /*
4375  * The function below are the high level ones.
4376  * only those ones must be called from the spoolss code.
4377  * JFM.
4378  */
4379
4380 /****************************************************************************
4381  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4382 ****************************************************************************/
4383
4384 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4385 {
4386         WERROR result;
4387
4388         dump_a_printer(printer, level);
4389
4390         switch (level) {
4391                 case 2:
4392                 {
4393                         /*
4394                          * Update the changestamp.  Emperical tests show that the
4395                          * ChangeID is always updated,but c_setprinter is
4396                          *  global spooler variable (not per printer).
4397                          */
4398
4399                         /* ChangeID **must** be increasing over the lifetime
4400                            of client's spoolss service in order for the
4401                            client's cache to show updates */
4402
4403                         printer->info_2->changeid = rev_changeid();
4404
4405                         /*
4406                          * Because one day someone will ask:
4407                          * NT->NT       An admin connection to a remote
4408                          *              printer show changes imeediately in
4409                          *              the properities dialog
4410                          *
4411                          *              A non-admin connection will only show the
4412                          *              changes after viewing the properites page
4413                          *              2 times.  Seems to be related to a
4414                          *              race condition in the client between the spooler
4415                          *              updating the local cache and the Explorer.exe GUI
4416                          *              actually displaying the properties.
4417                          *
4418                          *              This is fixed in Win2k.  admin/non-admin
4419                          *              connections both display changes immediately.
4420                          *
4421                          * 14/12/01     --jerry
4422                          */
4423
4424                         result=update_a_printer_2(printer->info_2);
4425                         break;
4426                 }
4427                 default:
4428                         result=WERR_UNKNOWN_LEVEL;
4429                         break;
4430         }
4431
4432         return result;
4433 }
4434
4435 /****************************************************************************
4436  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4437
4438  Previously the code had a memory allocation problem because it always
4439  used the TALLOC_CTX from the Printer_entry*.   This context lasts
4440  as a long as the original handle is open.  So if the client made a lot
4441  of getprinter[data]() calls, the memory usage would climb.  Now we use
4442  a short lived TALLOC_CTX for printer_info_2 objects returned.  We
4443  still use the Printer_entry->ctx for maintaining the cache copy though
4444  since that object must live as long as the handle by definition.
4445                                                     --jerry
4446
4447 ****************************************************************************/
4448
4449 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4450                         const char *sharename, bool get_loc_com)
4451 {
4452         WERROR result;
4453         fstring servername;
4454
4455         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4456
4457         if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4458                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4459                 return WERR_NOMEM;
4460         }
4461
4462         switch (level) {
4463                 case 2:
4464                         if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4465                                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4466                                 TALLOC_FREE( *pp_printer );
4467                                 return WERR_NOMEM;
4468                         }
4469
4470                         if ( print_hnd )
4471                                 fstrcpy( servername, print_hnd->servername );
4472                         else {
4473                                 fstrcpy( servername, "%L" );
4474                                 standard_sub_basic( "", "", servername,
4475                                                     sizeof(servername)-1 );
4476                         }
4477
4478                         result = get_a_printer_2( (*pp_printer)->info_2,
4479                                         servername, sharename, get_loc_com);
4480
4481                         /* we have a new printer now.  Save it with this handle */
4482
4483                         if ( !W_ERROR_IS_OK(result) ) {
4484                                 TALLOC_FREE( *pp_printer );
4485                                 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4486                                         sharename, (unsigned int)level, win_errstr(result)));
4487                                 return result;
4488                         }
4489
4490                         dump_a_printer( *pp_printer, level);
4491
4492                         break;
4493
4494                 default:
4495                         TALLOC_FREE( *pp_printer );
4496                         return WERR_UNKNOWN_LEVEL;
4497         }
4498
4499         return WERR_OK;
4500 }
4501
4502 WERROR get_a_printer( Printer_entry *print_hnd,
4503                         NT_PRINTER_INFO_LEVEL **pp_printer,
4504                         uint32 level,
4505                         const char *sharename)
4506 {
4507         return get_a_printer_internal(print_hnd, pp_printer, level,
4508                                         sharename, true);
4509 }
4510
4511 WERROR get_a_printer_search( Printer_entry *print_hnd,
4512                         NT_PRINTER_INFO_LEVEL **pp_printer,
4513                         uint32 level,
4514                         const char *sharename)
4515 {
4516         return get_a_printer_internal(print_hnd, pp_printer, level,
4517                                         sharename, false);
4518 }
4519
4520 /****************************************************************************
4521  Deletes a NT_PRINTER_INFO_LEVEL struct.
4522 ****************************************************************************/
4523
4524 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4525 {
4526         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4527
4528         if ( !printer )
4529                 return 0;
4530
4531         switch (level) {
4532                 case 2:
4533                         if ( printer->info_2 )
4534                                 free_nt_printer_info_level_2(&printer->info_2);
4535                         break;
4536
4537                 default:
4538                         DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4539                         return 1;
4540         }
4541
4542         TALLOC_FREE(*pp_printer);
4543
4544         return 0;
4545 }
4546
4547 /****************************************************************************
4548 ****************************************************************************/
4549
4550 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
4551                               struct spoolss_DriverInfo8 *_info8)
4552 {
4553         struct spoolss_DriverInfo8 info8;
4554
4555         ZERO_STRUCT(info8);
4556
4557         switch (r->level) {
4558         case 3:
4559                 info8.version           = r->info.info3->version;
4560                 info8.driver_name       = r->info.info3->driver_name;
4561                 info8.architecture      = r->info.info3->architecture;
4562                 info8.driver_path       = r->info.info3->driver_path;
4563                 info8.data_file         = r->info.info3->data_file;
4564                 info8.config_file       = r->info.info3->config_file;
4565                 info8.help_file         = r->info.info3->help_file;
4566                 info8.monitor_name      = r->info.info3->monitor_name;
4567                 info8.default_datatype  = r->info.info3->default_datatype;
4568                 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
4569                         info8.dependent_files   = r->info.info3->dependent_files->string;
4570                 }
4571                 break;
4572         case 6:
4573                 info8.version           = r->info.info6->version;
4574                 info8.driver_name       = r->info.info6->driver_name;
4575                 info8.architecture      = r->info.info6->architecture;
4576                 info8.driver_path       = r->info.info6->driver_path;
4577                 info8.data_file         = r->info.info6->data_file;
4578                 info8.config_file       = r->info.info6->config_file;
4579                 info8.help_file         = r->info.info6->help_file;
4580                 info8.monitor_name      = r->info.info6->monitor_name;
4581                 info8.default_datatype  = r->info.info6->default_datatype;
4582                 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
4583                         info8.dependent_files   = r->info.info6->dependent_files->string;
4584                 }
4585                 info8.driver_date       = r->info.info6->driver_date;
4586                 info8.driver_version    = r->info.info6->driver_version;
4587                 info8.manufacturer_name = r->info.info6->manufacturer_name;
4588                 info8.manufacturer_url  = r->info.info6->manufacturer_url;
4589                 info8.hardware_id       = r->info.info6->hardware_id;
4590                 info8.provider          = r->info.info6->provider;
4591                 break;
4592         case 8:
4593                 info8.version           = r->info.info8->version;
4594                 info8.driver_name       = r->info.info8->driver_name;
4595                 info8.architecture      = r->info.info8->architecture;
4596                 info8.driver_path       = r->info.info8->driver_path;
4597                 info8.data_file         = r->info.info8->data_file;
4598                 info8.config_file       = r->info.info8->config_file;
4599                 info8.help_file         = r->info.info8->help_file;
4600                 info8.monitor_name      = r->info.info8->monitor_name;
4601                 info8.default_datatype  = r->info.info8->default_datatype;
4602                 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
4603                         info8.dependent_files   = r->info.info8->dependent_files->string;
4604                 }
4605                 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
4606                         info8.previous_names    = r->info.info8->previous_names->string;
4607                 }
4608                 info8.driver_date       = r->info.info8->driver_date;
4609                 info8.driver_version    = r->info.info8->driver_version;
4610                 info8.manufacturer_name = r->info.info8->manufacturer_name;
4611                 info8.manufacturer_url  = r->info.info8->manufacturer_url;
4612                 info8.hardware_id       = r->info.info8->hardware_id;
4613                 info8.provider          = r->info.info8->provider;
4614                 info8.print_processor   = r->info.info8->print_processor;
4615                 info8.vendor_setup      = r->info.info8->vendor_setup;
4616                 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
4617                         info8.color_profiles = r->info.info8->color_profiles->string;
4618                 }
4619                 info8.inf_path          = r->info.info8->inf_path;
4620                 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
4621                 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
4622                         info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
4623                 }
4624                 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
4625                 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
4626                 break;
4627         default:
4628                 return false;
4629         }
4630
4631         *_info8 = info8;
4632
4633         return true;
4634 }
4635
4636
4637 uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx,
4638                               struct spoolss_AddDriverInfoCtr *r,
4639                               char **driver_name,
4640                               uint32_t *version)
4641 {
4642         struct spoolss_DriverInfo8 info8;
4643
4644         ZERO_STRUCT(info8);
4645
4646         DEBUG(10,("adding a printer at level [%d]\n", r->level));
4647
4648         if (!driver_info_ctr_to_info8(r, &info8)) {
4649                 return -1;
4650         }
4651
4652         *driver_name = talloc_strdup(mem_ctx, info8.driver_name);
4653         if (!*driver_name) {
4654                 return -1;
4655         }
4656         *version = info8.version;
4657
4658         return add_a_printer_driver_8(&info8);
4659 }
4660
4661 /****************************************************************************
4662 ****************************************************************************/
4663
4664 WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx,
4665                             struct spoolss_DriverInfo8 **driver,
4666                             const char *drivername, const char *architecture,
4667                             uint32_t version)
4668 {
4669         WERROR result;
4670         struct spoolss_DriverInfo3 info3;
4671         struct spoolss_DriverInfo8 *info8;
4672
4673         ZERO_STRUCT(info3);
4674
4675         /* Sometime we just want any version of the driver */
4676
4677         if (version == DRIVER_ANY_VERSION) {
4678                 /* look for Win2k first and then for NT4 */
4679                 result = get_a_printer_driver_3(mem_ctx,
4680                                                 &info3,
4681                                                 drivername,
4682                                                 architecture, 3);
4683                 if (!W_ERROR_IS_OK(result)) {
4684                         result = get_a_printer_driver_3(mem_ctx,
4685                                                         &info3,
4686                                                         drivername,
4687                                                         architecture, 2);
4688                 }
4689         } else {
4690                 result = get_a_printer_driver_3(mem_ctx,
4691                                                 &info3,
4692                                                 drivername,
4693                                                 architecture,
4694                                                 version);
4695         }
4696
4697         if (!W_ERROR_IS_OK(result)) {
4698                 return result;
4699         }
4700
4701         info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8);
4702         if (!info8) {
4703                 return WERR_NOMEM;
4704         }
4705
4706         info8->version          = info3.version;
4707         info8->driver_name      = info3.driver_name;
4708         info8->architecture     = info3.architecture;
4709         info8->driver_path      = info3.driver_path;
4710         info8->data_file        = info3.data_file;
4711         info8->config_file      = info3.config_file;
4712         info8->help_file        = info3.help_file;
4713         info8->dependent_files  = info3.dependent_files;
4714         info8->monitor_name     = info3.monitor_name;
4715         info8->default_datatype = info3.default_datatype;
4716
4717         *driver = info8;
4718
4719         return WERR_OK;
4720 }
4721
4722 /****************************************************************************
4723 ****************************************************************************/
4724
4725 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver)
4726 {
4727         talloc_free(driver);
4728         return 0;
4729 }
4730
4731
4732 /****************************************************************************
4733   Determine whether or not a particular driver is currently assigned
4734   to a printer
4735 ****************************************************************************/
4736
4737 bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r)
4738 {
4739         int snum;
4740         int n_services = lp_numservices();
4741         NT_PRINTER_INFO_LEVEL *printer = NULL;
4742         bool in_use = False;
4743
4744         if (!r) {
4745                 return false;
4746         }
4747
4748         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4749
4750         /* loop through the printers.tdb and check for the drivername */
4751
4752         for (snum=0; snum<n_services && !in_use; snum++) {
4753                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4754                         continue;
4755
4756                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4757                         continue;
4758
4759                 if (strequal(r->driver_name, printer->info_2->drivername))
4760                         in_use = True;
4761
4762                 free_a_printer( &printer, 2 );
4763         }
4764
4765         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4766
4767         if ( in_use ) {
4768                 struct spoolss_DriverInfo8 *d;
4769                 WERROR werr;
4770
4771                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
4772
4773                 /* we can still remove the driver if there is one of
4774                    "Windows NT x86" version 2 or 3 left */
4775
4776                 if (!strequal("Windows NT x86", r->architecture)) {
4777                         werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION);
4778                 }
4779                 else {
4780                         switch (r->version) {
4781                         case 2:
4782                                 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3);
4783                                 break;
4784                         case 3:
4785                                 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2);
4786                                 break;
4787                         default:
4788                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4789                                         r->version));
4790                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4791                                 break;
4792                         }
4793                 }
4794
4795                 /* now check the error code */
4796
4797                 if ( W_ERROR_IS_OK(werr) ) {
4798                         /* it's ok to remove the driver, we have other architctures left */
4799                         in_use = False;
4800                         free_a_printer_driver(d);
4801                 }
4802         }
4803
4804         /* report that the driver is not in use by default */
4805
4806         return in_use;
4807 }
4808
4809
4810 /**********************************************************************
4811  Check to see if a ogiven file is in use by *info
4812  *********************************************************************/
4813
4814 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
4815 {
4816         int i = 0;
4817
4818         if ( !info )
4819                 return False;
4820
4821         /* mz: skip files that are in the list but already deleted */
4822         if (!file || !file[0]) {
4823                 return false;
4824         }
4825
4826         if (strequal(file, info->driver_path))
4827                 return True;
4828
4829         if (strequal(file, info->data_file))
4830                 return True;
4831
4832         if (strequal(file, info->config_file))
4833                 return True;
4834
4835         if (strequal(file, info->help_file))
4836                 return True;
4837
4838         /* see of there are any dependent files to examine */
4839
4840         if (!info->dependent_files)
4841                 return False;
4842
4843         while (info->dependent_files[i] && *info->dependent_files[i]) {
4844                 if (strequal(file, info->dependent_files[i]))
4845                         return True;
4846                 i++;
4847         }
4848
4849         return False;
4850
4851 }
4852
4853 /**********************************************************************
4854  Utility function to remove the dependent file pointed to by the
4855  input parameter from the list
4856  *********************************************************************/
4857
4858 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
4859 {
4860
4861         /* bump everything down a slot */
4862
4863         while (files && files[idx+1]) {
4864                 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
4865                 idx++;
4866         }
4867
4868         files[idx] = NULL;
4869
4870         return;
4871 }
4872
4873 /**********************************************************************
4874  Check if any of the files used by src are also used by drv
4875  *********************************************************************/
4876
4877 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
4878                                    struct spoolss_DriverInfo8 *src,
4879                                    const struct spoolss_DriverInfo8 *drv)
4880 {
4881         bool    in_use = False;
4882         int     i = 0;
4883
4884         if ( !src || !drv )
4885                 return False;
4886
4887         /* check each file.  Remove it from the src structure if it overlaps */
4888
4889         if (drv_file_in_use(src->driver_path, drv)) {
4890                 in_use = True;
4891                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
4892                 src->driver_path = talloc_strdup(mem_ctx, "");
4893                 if (!src->driver_path) { return false; }
4894         }
4895
4896         if (drv_file_in_use(src->data_file, drv)) {
4897                 in_use = True;
4898                 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
4899                 src->data_file = talloc_strdup(mem_ctx, "");
4900                 if (!src->data_file) { return false; }
4901         }
4902
4903         if (drv_file_in_use(src->config_file, drv)) {
4904                 in_use = True;
4905                 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
4906                 src->config_file = talloc_strdup(mem_ctx, "");
4907                 if (!src->config_file) { return false; }
4908         }
4909
4910         if (drv_file_in_use(src->help_file, drv)) {
4911                 in_use = True;
4912                 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
4913                 src->help_file = talloc_strdup(mem_ctx, "");
4914                 if (!src->help_file) { return false; }
4915         }
4916
4917         /* are there any dependentfiles to examine? */
4918
4919         if (!src->dependent_files)
4920                 return in_use;
4921
4922         while (src->dependent_files[i] && *src->dependent_files[i]) {
4923                 if (drv_file_in_use(src->dependent_files[i], drv)) {
4924                         in_use = True;
4925                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
4926                         trim_dependent_file(mem_ctx, src->dependent_files, i);
4927                 } else
4928                         i++;
4929         }
4930
4931         return in_use;
4932 }
4933
4934 /****************************************************************************
4935   Determine whether or not a particular driver files are currently being
4936   used by any other driver.
4937
4938   Return value is True if any files were in use by other drivers
4939   and False otherwise.
4940
4941   Upon return, *info has been modified to only contain the driver files
4942   which are not in use
4943
4944   Fix from mz:
4945
4946   This needs to check all drivers to ensure that all files in use
4947   have been removed from *info, not just the ones in the first
4948   match.
4949 ****************************************************************************/
4950
4951 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
4952                                  struct spoolss_DriverInfo8 *info)
4953 {
4954         int                             i;
4955         int                             ndrivers;
4956         uint32                          version;
4957         fstring                         *list = NULL;
4958         struct spoolss_DriverInfo8      *driver;
4959         bool in_use = false;
4960
4961         if ( !info )
4962                 return False;
4963
4964         version = info->version;
4965
4966         /* loop over all driver versions */
4967
4968         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4969
4970         /* get the list of drivers */
4971
4972         list = NULL;
4973         ndrivers = get_ntdrivers(&list, info->architecture, version);
4974
4975         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4976                 ndrivers, info->architecture, version));
4977
4978         /* check each driver for overlap in files */
4979
4980         for (i=0; i<ndrivers; i++) {
4981                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4982
4983                 driver = NULL;
4984
4985                 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, list[i], info->architecture, version))) {
4986                         SAFE_FREE(list);
4987                         return True;
4988                 }
4989
4990                 /* check if d2 uses any files from d1 */
4991                 /* only if this is a different driver than the one being deleted */
4992
4993                 if (!strequal(info->driver_name, driver->driver_name)) {
4994                         if (trim_overlap_drv_files(mem_ctx, info, driver)) {
4995                                 /* mz: Do not instantly return -
4996                                  * we need to ensure this file isn't
4997                                  * also in use by other drivers. */
4998                                 in_use = true;
4999                         }
5000                 }
5001
5002                 free_a_printer_driver(driver);
5003         }
5004
5005         SAFE_FREE(list);
5006
5007         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5008
5009         return in_use;
5010 }
5011
5012 static NTSTATUS driver_unlink_internals(connection_struct *conn,
5013                                         const char *name)
5014 {
5015         struct smb_filename *smb_fname = NULL;
5016         NTSTATUS status;
5017
5018         status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
5019             &smb_fname);
5020         if (!NT_STATUS_IS_OK(status)) {
5021                 return status;
5022         }
5023
5024         status = unlink_internals(conn, NULL, 0, smb_fname, false);
5025
5026         TALLOC_FREE(smb_fname);
5027         return status;
5028 }
5029
5030 /****************************************************************************
5031   Actually delete the driver files.  Make sure that
5032   printer_driver_files_in_use() return False before calling
5033   this.
5034 ****************************************************************************/
5035
5036 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
5037                                 const struct spoolss_DriverInfo8 *r)
5038 {
5039         int i = 0;
5040         char *s;
5041         const char *file;
5042         connection_struct *conn;
5043         NTSTATUS nt_status;
5044         char *oldcwd;
5045         fstring printdollar;
5046         int printdollar_snum;
5047         bool ret = false;
5048
5049         if (!r) {
5050                 return false;
5051         }
5052
5053         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
5054                 r->driver_name, r->version));
5055
5056         fstrcpy(printdollar, "print$");
5057
5058         printdollar_snum = find_service(printdollar);
5059         if (printdollar_snum == -1) {
5060                 return false;
5061         }
5062
5063         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5064                                        lp_pathname(printdollar_snum),
5065                                        rpc_pipe->server_info, &oldcwd);
5066         if (!NT_STATUS_IS_OK(nt_status)) {
5067                 DEBUG(0,("delete_driver_files: create_conn_struct "
5068                          "returned %s\n", nt_errstr(nt_status)));
5069                 return false;
5070         }
5071
5072         if ( !CAN_WRITE(conn) ) {
5073                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5074                 goto fail;
5075         }
5076
5077         /* now delete the files; must strip the '\print$' string from
5078            fron of path                                                */
5079
5080         if (r->driver_path && r->driver_path[0]) {
5081                 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
5082                         file = s;
5083                         DEBUG(10,("deleting driverfile [%s]\n", s));
5084                         driver_unlink_internals(conn, file);
5085                 }
5086         }
5087
5088         if (r->config_file && r->config_file[0]) {
5089                 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
5090                         file = s;
5091                         DEBUG(10,("deleting configfile [%s]\n", s));
5092                         driver_unlink_internals(conn, file);
5093                 }
5094         }
5095
5096         if (r->data_file && r->data_file[0]) {
5097                 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
5098                         file = s;
5099                         DEBUG(10,("deleting datafile [%s]\n", s));
5100                         driver_unlink_internals(conn, file);
5101                 }
5102         }
5103
5104         if (r->help_file && r->help_file[0]) {
5105                 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
5106                         file = s;
5107                         DEBUG(10,("deleting helpfile [%s]\n", s));
5108                         driver_unlink_internals(conn, file);
5109                 }
5110         }
5111
5112         /* check if we are done removing files */
5113
5114         if (r->dependent_files) {
5115                 while (r->dependent_files[i] && r->dependent_files[i][0]) {
5116                         char *p;
5117
5118                         /* bypass the "\print$" portion of the path */
5119
5120                         if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
5121                                 file = p;
5122                                 DEBUG(10,("deleting dependent file [%s]\n", file));
5123                                 driver_unlink_internals(conn, file);
5124                         }
5125
5126                         i++;
5127                 }
5128         }
5129
5130         goto done;
5131  fail:
5132         ret = false;
5133  done:
5134         if (conn != NULL) {
5135                 vfs_ChDir(conn, oldcwd);
5136                 conn_free(conn);
5137         }
5138         return ret;
5139 }
5140
5141 /****************************************************************************
5142  Remove a printer driver from the TDB.  This assumes that the the driver was
5143  previously looked up.
5144  ***************************************************************************/
5145
5146 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5147                              const struct spoolss_DriverInfo8 *r,
5148                              uint32 version, bool delete_files )
5149 {
5150         char *key = NULL;
5151         const char     *arch;
5152         TDB_DATA        dbuf;
5153
5154         /* delete the tdb data first */
5155
5156         arch = get_short_archi(r->architecture);
5157         if (!arch) {
5158                 return WERR_UNKNOWN_PRINTER_DRIVER;
5159         }
5160         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5161                         arch, version, r->driver_name) < 0) {
5162                 return WERR_NOMEM;
5163         }
5164
5165         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5166                 key, delete_files ? "TRUE" : "FALSE" ));
5167
5168         /* check if the driver actually exists for this environment */
5169
5170         dbuf = tdb_fetch_bystring( tdb_drivers, key );
5171         if ( !dbuf.dptr ) {
5172                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5173                 SAFE_FREE(key);
5174                 return WERR_UNKNOWN_PRINTER_DRIVER;
5175         }
5176
5177         SAFE_FREE( dbuf.dptr );
5178
5179         /* ok... the driver exists so the delete should return success */
5180
5181         if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5182                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5183                 SAFE_FREE(key);
5184                 return WERR_ACCESS_DENIED;
5185         }
5186
5187         /*
5188          * now delete any associated files if delete_files == True
5189          * even if this part failes, we return succes because the
5190          * driver doesn not exist any more
5191          */
5192
5193         if ( delete_files )
5194                 delete_driver_files(rpc_pipe, r);
5195
5196         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5197         SAFE_FREE(key);
5198
5199         return WERR_OK;
5200 }
5201
5202 /****************************************************************************
5203  Store a security desc for a printer.
5204 ****************************************************************************/
5205
5206 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
5207 {
5208         struct sec_desc_buf *new_secdesc_ctr = NULL;
5209         struct sec_desc_buf *old_secdesc_ctr = NULL;
5210         TALLOC_CTX *mem_ctx = NULL;
5211         TDB_DATA kbuf;
5212         TDB_DATA dbuf;
5213         DATA_BLOB blob;
5214         WERROR status;
5215         NTSTATUS nt_status;
5216
5217         mem_ctx = talloc_init("nt_printing_setsec");
5218         if (mem_ctx == NULL)
5219                 return WERR_NOMEM;
5220
5221         /* The old owner and group sids of the security descriptor are not
5222            present when new ACEs are added or removed by changing printer
5223            permissions through NT.  If they are NULL in the new security
5224            descriptor then copy them over from the old one. */
5225
5226         if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5227                 DOM_SID *owner_sid, *group_sid;
5228                 struct security_acl *dacl, *sacl;
5229                 struct security_descriptor *psd = NULL;
5230                 size_t size;
5231
5232                 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5233                         status = WERR_NOMEM;
5234                         goto out;
5235                 }
5236
5237                 /* Pick out correct owner and group sids */
5238
5239                 owner_sid = secdesc_ctr->sd->owner_sid ?
5240                         secdesc_ctr->sd->owner_sid :
5241                         old_secdesc_ctr->sd->owner_sid;
5242
5243                 group_sid = secdesc_ctr->sd->group_sid ?
5244                         secdesc_ctr->sd->group_sid :
5245                         old_secdesc_ctr->sd->group_sid;
5246
5247                 dacl = secdesc_ctr->sd->dacl ?
5248                         secdesc_ctr->sd->dacl :
5249                         old_secdesc_ctr->sd->dacl;
5250
5251                 sacl = secdesc_ctr->sd->sacl ?
5252                         secdesc_ctr->sd->sacl :
5253                         old_secdesc_ctr->sd->sacl;
5254
5255                 /* Make a deep copy of the security descriptor */
5256
5257                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5258                                     owner_sid, group_sid,
5259                                     sacl,
5260                                     dacl,
5261                                     &size);
5262
5263                 if (!psd) {
5264                         status = WERR_NOMEM;
5265                         goto out;
5266                 }
5267
5268                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5269         }
5270
5271         if (!new_secdesc_ctr) {
5272                 new_secdesc_ctr = secdesc_ctr;
5273         }
5274
5275         /* Store the security descriptor in a tdb */
5276
5277         nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5278                                           &blob.data, &blob.length);
5279         if (!NT_STATUS_IS_OK(nt_status)) {
5280                 status = ntstatus_to_werror(nt_status);
5281                 goto out;
5282         }
5283
5284         kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5285
5286         dbuf.dptr = (unsigned char *)blob.data;
5287         dbuf.dsize = blob.length;
5288
5289         if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5290                 status = WERR_OK;
5291         } else {
5292                 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5293                 status = WERR_BADFUNC;
5294         }
5295
5296         /* Free malloc'ed memory */
5297         talloc_free(blob.data);
5298
5299  out:
5300
5301         if (mem_ctx)
5302                 talloc_destroy(mem_ctx);
5303         return status;
5304 }
5305
5306 /****************************************************************************
5307  Construct a default security descriptor buffer for a printer.
5308 ****************************************************************************/
5309
5310 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
5311 {
5312         struct security_ace ace[5];     /* max number of ace entries */
5313         int i = 0;
5314         uint32_t sa;
5315         struct security_acl *psa = NULL;
5316         struct sec_desc_buf *sdb = NULL;
5317         struct security_descriptor *psd = NULL;
5318         DOM_SID adm_sid;
5319         size_t sd_size;
5320
5321         /* Create an ACE where Everyone is allowed to print */
5322
5323         sa = PRINTER_ACE_PRINT;
5324         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5325                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5326
5327         /* Add the domain admins group if we are a DC */
5328
5329         if ( IS_DC ) {
5330                 DOM_SID domadmins_sid;
5331
5332                 sid_compose(&domadmins_sid, get_global_sam_sid(),
5333                             DOMAIN_RID_ADMINS);
5334
5335                 sa = PRINTER_ACE_FULL_CONTROL;
5336                 init_sec_ace(&ace[i++], &domadmins_sid,
5337                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5338                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5339                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5340                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5341         }
5342         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5343                 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
5344
5345                 sa = PRINTER_ACE_FULL_CONTROL;
5346                 init_sec_ace(&ace[i++], &adm_sid,
5347                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5348                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5349                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5350                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5351         }
5352
5353         /* add BUILTIN\Administrators as FULL CONTROL */
5354
5355         sa = PRINTER_ACE_FULL_CONTROL;
5356         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5357                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5358                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5359         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5360                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5361                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5362
5363         /* Make the security descriptor owned by the BUILTIN\Administrators */
5364
5365         /* The ACL revision number in rpc_secdesc.h differs from the one
5366            created by NT when setting ACE entries in printer
5367            descriptors.  NT4 complains about the property being edited by a
5368            NT5 machine. */
5369
5370         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5371                 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
5372                         &global_sid_Builtin_Administrators,
5373                         &global_sid_Builtin_Administrators,
5374                         NULL, psa, &sd_size);
5375         }
5376
5377         if (!psd) {
5378                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5379                 return NULL;
5380         }
5381
5382         sdb = make_sec_desc_buf(ctx, sd_size, psd);
5383
5384         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5385                  (unsigned int)sd_size));
5386
5387         return sdb;
5388 }
5389
5390 /****************************************************************************
5391  Get a security desc for a printer.
5392 ****************************************************************************/
5393
5394 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
5395 {
5396         TDB_DATA kbuf;
5397         TDB_DATA dbuf;
5398         DATA_BLOB blob;
5399         char *temp;
5400         NTSTATUS status;
5401
5402         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5403                 sharename = temp + 1;
5404         }
5405
5406         /* Fetch security descriptor from tdb */
5407
5408         kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5409
5410         dbuf = tdb_fetch(tdb_printers, kbuf);
5411         if (dbuf.dptr) {
5412
5413                 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5414                                                  secdesc_ctr);
5415                 SAFE_FREE(dbuf.dptr);
5416
5417                 if (NT_STATUS_IS_OK(status)) {
5418                         return true;
5419                 }
5420         }
5421
5422         *secdesc_ctr = construct_default_printer_sdb(ctx);
5423         if (!*secdesc_ctr) {
5424                 return false;
5425         }
5426
5427         status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5428                                        &blob.data, &blob.length);
5429         if (NT_STATUS_IS_OK(status)) {
5430                 dbuf.dptr = (unsigned char *)blob.data;
5431                 dbuf.dsize = blob.length;
5432                 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5433                 talloc_free(blob.data);
5434         }
5435
5436         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5437            this security descriptor has been created when winbindd was
5438            down.  Take ownership of security descriptor. */
5439
5440         if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5441                 DOM_SID owner_sid;
5442
5443                 /* Change sd owner to workgroup administrator */
5444
5445                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5446                         struct sec_desc_buf *new_secdesc_ctr = NULL;
5447                         struct security_descriptor *psd = NULL;
5448                         size_t size;
5449
5450                         /* Create new sd */
5451
5452                         sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
5453
5454                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5455                                             &owner_sid,
5456                                             (*secdesc_ctr)->sd->group_sid,
5457                                             (*secdesc_ctr)->sd->sacl,
5458                                             (*secdesc_ctr)->sd->dacl,
5459                                             &size);
5460
5461                         if (!psd) {
5462                                 return False;
5463                         }
5464
5465                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5466                         if (!new_secdesc_ctr) {
5467                                 return False;
5468                         }
5469
5470                         /* Swap with other one */
5471
5472                         *secdesc_ctr = new_secdesc_ctr;
5473
5474                         /* Set it */
5475
5476                         nt_printing_setsec(sharename, *secdesc_ctr);
5477                 }
5478         }
5479
5480         if (DEBUGLEVEL >= 10) {
5481                 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
5482                 int i;
5483
5484                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5485                            sharename, the_acl->num_aces));
5486
5487                 for (i = 0; i < the_acl->num_aces; i++) {
5488                         DEBUG(10, ("%s %d %d 0x%08x\n",
5489                                    sid_string_dbg(&the_acl->aces[i].trustee),
5490                                    the_acl->aces[i].type, the_acl->aces[i].flags,
5491                                    the_acl->aces[i].access_mask));
5492                 }
5493         }
5494
5495         return True;
5496 }
5497
5498 /* error code:
5499         0: everything OK
5500         1: level not implemented
5501         2: file doesn't exist
5502         3: can't allocate memory
5503         4: can't free memory
5504         5: non existant struct
5505 */
5506
5507 /*
5508         A printer and a printer driver are 2 different things.
5509         NT manages them separatelly, Samba does the same.
5510         Why ? Simply because it's easier and it makes sense !
5511
5512         Now explanation: You have 3 printers behind your samba server,
5513         2 of them are the same make and model (laser A and B). But laser B
5514         has an 3000 sheet feeder and laser A doesn't such an option.
5515         Your third printer is an old dot-matrix model for the accounting :-).
5516
5517         If the /usr/local/samba/lib directory (default dir), you will have
5518         5 files to describe all of this.
5519
5520         3 files for the printers (1 by printer):
5521                 NTprinter_laser A
5522                 NTprinter_laser B
5523                 NTprinter_accounting
5524         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5525                 NTdriver_printer model X
5526                 NTdriver_printer model Y
5527
5528 jfm: I should use this comment for the text file to explain
5529         same thing for the forms BTW.
5530         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5531
5532 */
5533
5534 /* Convert generic access rights to printer object specific access rights.
5535    It turns out that NT4 security descriptors use generic access rights and
5536    NT5 the object specific ones. */
5537
5538 void map_printer_permissions(struct security_descriptor *sd)
5539 {
5540         int i;
5541
5542         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5543                 se_map_generic(&sd->dacl->aces[i].access_mask,
5544                                &printer_generic_mapping);
5545         }
5546 }
5547
5548 void map_job_permissions(struct security_descriptor *sd)
5549 {
5550         int i;
5551
5552         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5553                 se_map_generic(&sd->dacl->aces[i].access_mask,
5554                                &job_generic_mapping);
5555         }
5556 }
5557
5558
5559 /****************************************************************************
5560  Check a user has permissions to perform the given operation.  We use the
5561  permission constants defined in include/rpc_spoolss.h to check the various
5562  actions we perform when checking printer access.
5563
5564    PRINTER_ACCESS_ADMINISTER:
5565        print_queue_pause, print_queue_resume, update_printer_sec,
5566        update_printer, spoolss_addprinterex_level_2,
5567        _spoolss_setprinterdata
5568
5569    PRINTER_ACCESS_USE:
5570        print_job_start
5571
5572    JOB_ACCESS_ADMINISTER:
5573        print_job_delete, print_job_pause, print_job_resume,
5574        print_queue_purge
5575
5576   Try access control in the following order (for performance reasons):
5577     1)  root and SE_PRINT_OPERATOR can do anything (easy check)
5578     2)  check security descriptor (bit comparisons in memory)
5579     3)  "printer admins" (may result in numerous calls to winbind)
5580
5581  ****************************************************************************/
5582 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5583                         int access_type)
5584 {
5585         struct sec_desc_buf *secdesc = NULL;
5586         uint32 access_granted;
5587         NTSTATUS status;
5588         const char *pname;
5589         TALLOC_CTX *mem_ctx = NULL;
5590         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5591
5592         /* If user is NULL then use the current_user structure */
5593
5594         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5595
5596         if (server_info->utok.uid == sec_initial_uid()
5597             || user_has_privileges(server_info->ptok, &se_printop ) ) {
5598                 return True;
5599         }
5600
5601         /* Get printer name */
5602
5603         pname = PRINTERNAME(snum);
5604
5605         if (!pname || !*pname) {
5606                 errno = EACCES;
5607                 return False;
5608         }
5609
5610         /* Get printer security descriptor */
5611
5612         if(!(mem_ctx = talloc_init("print_access_check"))) {
5613                 errno = ENOMEM;
5614                 return False;
5615         }
5616
5617         if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5618                 talloc_destroy(mem_ctx);
5619                 errno = ENOMEM;
5620                 return False;
5621         }
5622
5623         if (access_type == JOB_ACCESS_ADMINISTER) {
5624                 struct sec_desc_buf *parent_secdesc = secdesc;
5625
5626                 /* Create a child security descriptor to check permissions
5627                    against.  This is because print jobs are child objects
5628                    objects of a printer. */
5629
5630                 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5631
5632                 if (!NT_STATUS_IS_OK(status)) {
5633                         talloc_destroy(mem_ctx);
5634                         errno = map_errno_from_nt_status(status);
5635                         return False;
5636                 }
5637
5638                 map_job_permissions(secdesc->sd);
5639         } else {
5640                 map_printer_permissions(secdesc->sd);
5641         }
5642
5643         /* Check access */
5644         status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5645                                  &access_granted);
5646
5647         DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5648
5649         /* see if we need to try the printer admin list */
5650
5651         if (!NT_STATUS_IS_OK(status) &&
5652             (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5653                                          NULL, NULL, server_info->ptok,
5654                                          lp_printer_admin(snum)))) {
5655                 talloc_destroy(mem_ctx);
5656                 return True;
5657         }
5658
5659         talloc_destroy(mem_ctx);
5660
5661         if (!NT_STATUS_IS_OK(status)) {
5662                 errno = EACCES;
5663         }
5664
5665         return NT_STATUS_IS_OK(status);
5666 }
5667
5668 /****************************************************************************
5669  Check the time parameters allow a print operation.
5670 *****************************************************************************/
5671
5672 bool print_time_access_check(const char *servicename)
5673 {
5674         NT_PRINTER_INFO_LEVEL *printer = NULL;
5675         bool ok = False;
5676         time_t now = time(NULL);
5677         struct tm *t;
5678         uint32 mins;
5679
5680         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5681                 return False;
5682
5683         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5684                 ok = True;
5685
5686         t = gmtime(&now);
5687         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5688
5689         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5690                 ok = True;
5691
5692         free_a_printer(&printer, 2);
5693
5694         if (!ok)
5695                 errno = EACCES;
5696
5697         return ok;
5698 }
5699
5700 /****************************************************************************
5701  Fill in the servername sent in the _spoolss_open_printer_ex() call
5702 ****************************************************************************/
5703
5704 char* get_server_name( Printer_entry *printer )
5705 {
5706         return printer->servername;
5707 }
5708
5709