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