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