s3-secdesc: use SD_REVISION from security.idl.
[obnox/samba/samba-obnox.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 *last_from;
3855 static char *last_to;
3856
3857 static const char *get_last_from(void)
3858 {
3859         if (!last_from) {
3860                 return "";
3861         }
3862         return last_from;
3863 }
3864
3865 static const char *get_last_to(void)
3866 {
3867         if (!last_to) {
3868                 return "";
3869         }
3870         return last_to;
3871 }
3872
3873 static bool set_last_from_to(const char *from, const char *to)
3874 {
3875         char *orig_from = last_from;
3876         char *orig_to = last_to;
3877
3878         last_from = SMB_STRDUP(from);
3879         last_to = SMB_STRDUP(to);
3880
3881         SAFE_FREE(orig_from);
3882         SAFE_FREE(orig_to);
3883
3884         if (!last_from || !last_to) {
3885                 SAFE_FREE(last_from);
3886                 SAFE_FREE(last_to);
3887                 return false;
3888         }
3889         return true;
3890 }
3891
3892 static void map_to_os2_driver(fstring drivername)
3893 {
3894         char *mapfile = lp_os2_driver_map();
3895         char **lines = NULL;
3896         int numlines = 0;
3897         int i;
3898
3899         if (!strlen(drivername))
3900                 return;
3901
3902         if (!*mapfile)
3903                 return;
3904
3905         if (strequal(drivername,get_last_from())) {
3906                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3907                         drivername,get_last_to()));
3908                 fstrcpy(drivername,get_last_to());
3909                 return;
3910         }
3911
3912         lines = file_lines_load(mapfile, &numlines,0,NULL);
3913         if (numlines == 0 || lines == NULL) {
3914                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3915                 TALLOC_FREE(lines);
3916                 return;
3917         }
3918
3919         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3920
3921         for( i = 0; i < numlines; i++) {
3922                 char *nt_name = lines[i];
3923                 char *os2_name = strchr(nt_name,'=');
3924
3925                 if (!os2_name)
3926                         continue;
3927
3928                 *os2_name++ = 0;
3929
3930                 while (isspace(*nt_name))
3931                         nt_name++;
3932
3933                 if (!*nt_name || strchr("#;",*nt_name))
3934                         continue;
3935
3936                 {
3937                         int l = strlen(nt_name);
3938                         while (l && isspace(nt_name[l-1])) {
3939                                 nt_name[l-1] = 0;
3940                                 l--;
3941                         }
3942                 }
3943
3944                 while (isspace(*os2_name))
3945                         os2_name++;
3946
3947                 {
3948                         int l = strlen(os2_name);
3949                         while (l && isspace(os2_name[l-1])) {
3950                                 os2_name[l-1] = 0;
3951                                 l--;
3952                         }
3953                 }
3954
3955                 if (strequal(nt_name,drivername)) {
3956                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3957                         set_last_from_to(drivername,os2_name);
3958                         fstrcpy(drivername,os2_name);
3959                         TALLOC_FREE(lines);
3960                         return;
3961                 }
3962         }
3963
3964         TALLOC_FREE(lines);
3965 }
3966
3967 /****************************************************************************
3968  Get a default printer info 2 struct.
3969 ****************************************************************************/
3970
3971 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
3972                                 const char *servername,
3973                                 const char* sharename,
3974                                 bool get_loc_com)
3975 {
3976         int snum = lp_servicenumber(sharename);
3977
3978         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3979         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3980                 servername, sharename);
3981         fstrcpy(info->sharename, sharename);
3982         fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3983
3984         /* by setting the driver name to an empty string, a local NT admin
3985            can now run the **local** APW to install a local printer driver
3986            for a Samba shared printer in 2.2.  Without this, drivers **must** be
3987            installed on the Samba server for NT clients --jerry */
3988 #if 0   /* JERRY --do not uncomment-- */
3989         if (!*info->drivername)
3990                 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3991 #endif
3992
3993
3994         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3995
3996         strlcpy(info->comment, "", sizeof(info->comment));
3997         fstrcpy(info->printprocessor, "winprint");
3998         fstrcpy(info->datatype, "RAW");
3999
4000 #ifdef HAVE_CUPS
4001         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4002                 /* Pull the location and comment strings from cups if we don't
4003                    already have one */
4004                 if ( !strlen(info->location) || !strlen(info->comment) ) {
4005                         char *comment = NULL;
4006                         char *location = NULL;
4007                         if (cups_pull_comment_location(info, info->sharename,
4008                                                        &comment, &location)) {
4009                                 strlcpy(info->comment, comment, sizeof(info->comment));
4010                                 fstrcpy(info->location, location);
4011                                 TALLOC_FREE(comment);
4012                                 TALLOC_FREE(location);
4013                         }
4014                 }
4015         }
4016 #endif
4017
4018         info->attributes = PRINTER_ATTRIBUTE_SAMBA;
4019
4020         info->starttime = 0; /* Minutes since 12:00am GMT */
4021         info->untiltime = 0; /* Minutes since 12:00am GMT */
4022         info->priority = 1;
4023         info->default_priority = 1;
4024         info->setuptime = (uint32)time(NULL);
4025
4026         /*
4027          * I changed this as I think it is better to have a generic
4028          * DEVMODE than to crash Win2k explorer.exe   --jerry
4029          * See the HP Deskjet 990c Win2k drivers for an example.
4030          *
4031          * However the default devmode appears to cause problems
4032          * with the HP CLJ 8500 PCL driver.  Hence the addition of
4033          * the "default devmode" parameter   --jerry 22/01/2002
4034          */
4035
4036         if (lp_default_devmode(snum)) {
4037                 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
4038                         goto fail;
4039                 }
4040         } else {
4041                 info->devmode = NULL;
4042         }
4043
4044         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4045                 goto fail;
4046         }
4047
4048         info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
4049         if (!info->data) {
4050                 goto fail;
4051         }
4052
4053         add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
4054
4055         return WERR_OK;
4056
4057 fail:
4058         if (info->devmode)
4059                 free_nt_devicemode(&info->devmode);
4060
4061         return WERR_ACCESS_DENIED;
4062 }
4063
4064 /****************************************************************************
4065 ****************************************************************************/
4066
4067 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
4068                                 const char *servername,
4069                                 const char *sharename,
4070                                 bool get_loc_com)
4071 {
4072         int len = 0;
4073         int snum = lp_servicenumber(sharename);
4074         TDB_DATA kbuf, dbuf;
4075         fstring printername;
4076         char adevice[MAXDEVICENAME];
4077         char *comment = NULL;
4078
4079         kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4080
4081         dbuf = tdb_fetch(tdb_printers, kbuf);
4082         if (!dbuf.dptr) {
4083                 return get_a_printer_2_default(info, servername,
4084                                         sharename, get_loc_com);
4085         }
4086
4087         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4088                         &info->attributes,
4089                         &info->priority,
4090                         &info->default_priority,
4091                         &info->starttime,
4092                         &info->untiltime,
4093                         &info->status,
4094                         &info->cjobs,
4095                         &info->averageppm,
4096                         &info->changeid,
4097                         &info->c_setprinter,
4098                         &info->setuptime,
4099                         info->servername,
4100                         info->printername,
4101                         info->sharename,
4102                         info->portname,
4103                         info->drivername,
4104                         &comment,
4105                         info->location,
4106                         info->sepfile,
4107                         info->printprocessor,
4108                         info->datatype,
4109                         info->parameters);
4110
4111         if (comment) {
4112                 strlcpy(info->comment, comment, sizeof(info->comment));
4113                 SAFE_FREE(comment);
4114         }
4115
4116         /* Samba has to have shared raw drivers. */
4117         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4118         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4119
4120         /* Restore the stripped strings. */
4121         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4122
4123         if ( lp_force_printername(snum) ) {
4124                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4125         } else {
4126                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4127         }
4128
4129         fstrcpy(info->printername, printername);
4130
4131 #ifdef HAVE_CUPS
4132         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4133                 /* Pull the location and comment strings from cups if we don't
4134                    already have one */
4135                 if ( !strlen(info->location) || !strlen(info->comment) ) {
4136                         char *location = NULL;
4137                         comment = NULL;
4138                         if (cups_pull_comment_location(info, info->sharename,
4139                                                        &comment, &location)) {
4140                                 strlcpy(info->comment, comment, sizeof(info->comment));
4141                                 fstrcpy(info->location, location);
4142                                 TALLOC_FREE(comment);
4143                                 TALLOC_FREE(location);
4144                         }
4145                 }
4146         }
4147 #endif
4148
4149         len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4150
4151         /*
4152          * Some client drivers freak out if there is a NULL devmode
4153          * (probably the driver is not checking before accessing
4154          * the devmode pointer)   --jerry
4155          *
4156          * See comments in get_a_printer_2_default()
4157          */
4158
4159         if (lp_default_devmode(snum) && !info->devmode) {
4160                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4161                         printername));
4162                 info->devmode = construct_nt_devicemode(printername);
4163         }
4164
4165         slprintf( adevice, sizeof(adevice), "%s", info->printername );
4166         if (info->devmode) {
4167                 fstrcpy(info->devmode->devicename, adevice);
4168         }
4169
4170         if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4171                 DEBUG(0,("unpack_values: talloc() failed!\n"));
4172                 SAFE_FREE(dbuf.dptr);
4173                 return WERR_NOMEM;
4174         }
4175         len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4176
4177         /* This will get the current RPC talloc context, but we should be
4178            passing this as a parameter... fixme... JRA ! */
4179
4180         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4181                 SAFE_FREE(dbuf.dptr);
4182                 return WERR_NOMEM;
4183         }
4184
4185         /* Fix for OS/2 drivers. */
4186
4187         if (get_remote_arch() == RA_OS2) {
4188                 map_to_os2_driver(info->drivername);
4189         }
4190
4191         SAFE_FREE(dbuf.dptr);
4192
4193         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4194                  sharename, info->printername, info->drivername));
4195
4196         return WERR_OK;
4197 }
4198
4199 /****************************************************************************
4200  Debugging function, dump at level 6 the struct in the logs.
4201 ****************************************************************************/
4202 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4203 {
4204         uint32 result;
4205         NT_PRINTER_INFO_LEVEL_2 *info2;
4206
4207         DEBUG(106,("Dumping printer at level [%d]\n", level));
4208
4209         switch (level) {
4210                 case 2:
4211                 {
4212                         if (printer->info_2 == NULL)
4213                                 result=5;
4214                         else
4215                         {
4216                                 info2=printer->info_2;
4217
4218                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4219                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4220                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4221                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4222                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4223                                 DEBUGADD(106,("status:[%d]\n", info2->status));
4224                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4225                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4226                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4227                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4228                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4229
4230                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4231                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4232                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4233                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4234                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4235                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4236                                 DEBUGADD(106,("location:[%s]\n", info2->location));
4237                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4238                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4239                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4240                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4241                                 result=0;
4242                         }
4243                         break;
4244                 }
4245                 default:
4246                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4247                         result=1;
4248                         break;
4249         }
4250
4251         return result;
4252 }
4253
4254 /****************************************************************************
4255  Update the changeid time.
4256  This is SO NASTY as some drivers need this to change, others need it
4257  static. This value will change every second, and I must hope that this
4258  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4259  UTAH ! JRA.
4260 ****************************************************************************/
4261
4262 static uint32 rev_changeid(void)
4263 {
4264         struct timeval tv;
4265
4266         get_process_uptime(&tv);
4267
4268 #if 1   /* JERRY */
4269         /* Return changeid as msec since spooler restart */
4270         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4271 #else
4272         /*
4273          * This setting seems to work well but is too untested
4274          * to replace the above calculation.  Left in for experiementation
4275          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
4276          */
4277         return tv.tv_sec * 10 + tv.tv_usec / 100000;
4278 #endif
4279 }
4280
4281
4282 /*
4283  * The function below are the high level ones.
4284  * only those ones must be called from the spoolss code.
4285  * JFM.
4286  */
4287
4288 /****************************************************************************
4289  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4290 ****************************************************************************/
4291
4292 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4293 {
4294         WERROR result;
4295
4296         dump_a_printer(printer, level);
4297
4298         switch (level) {
4299                 case 2:
4300                 {
4301                         /*
4302                          * Update the changestamp.  Emperical tests show that the
4303                          * ChangeID is always updated,but c_setprinter is
4304                          *  global spooler variable (not per printer).
4305                          */
4306
4307                         /* ChangeID **must** be increasing over the lifetime
4308                            of client's spoolss service in order for the
4309                            client's cache to show updates */
4310
4311                         printer->info_2->changeid = rev_changeid();
4312
4313                         /*
4314                          * Because one day someone will ask:
4315                          * NT->NT       An admin connection to a remote
4316                          *              printer show changes imeediately in
4317                          *              the properities dialog
4318                          *
4319                          *              A non-admin connection will only show the
4320                          *              changes after viewing the properites page
4321                          *              2 times.  Seems to be related to a
4322                          *              race condition in the client between the spooler
4323                          *              updating the local cache and the Explorer.exe GUI
4324                          *              actually displaying the properties.
4325                          *
4326                          *              This is fixed in Win2k.  admin/non-admin
4327                          *              connections both display changes immediately.
4328                          *
4329                          * 14/12/01     --jerry
4330                          */
4331
4332                         result=update_a_printer_2(printer->info_2);
4333                         break;
4334                 }
4335                 default:
4336                         result=WERR_UNKNOWN_LEVEL;
4337                         break;
4338         }
4339
4340         return result;
4341 }
4342
4343 /****************************************************************************
4344  Initialize printer devmode & data with previously saved driver init values.
4345 ****************************************************************************/
4346
4347 static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4348 {
4349         int                     len = 0;
4350         char *key = NULL;
4351         TDB_DATA                dbuf;
4352         NT_PRINTER_INFO_LEVEL_2 info;
4353
4354
4355         ZERO_STRUCT(info);
4356
4357         /*
4358          * Delete any printer data 'values' already set. When called for driver
4359          * replace, there will generally be some, but during an add printer, there
4360          * should not be any (if there are delete them).
4361          */
4362
4363         if ( info_ptr->data )
4364                 delete_all_printer_data( info_ptr, "" );
4365
4366         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX,
4367                                 info_ptr->drivername) < 0) {
4368                 return false;
4369         }
4370
4371         dbuf = tdb_fetch_bystring(tdb_drivers, key);
4372         if (!dbuf.dptr) {
4373                 /*
4374                  * When changing to a driver that has no init info in the tdb, remove
4375                  * the previous drivers init info and leave the new on blank.
4376                  */
4377                 free_nt_devicemode(&info_ptr->devmode);
4378                 SAFE_FREE(key);
4379                 return false;
4380         }
4381
4382         SAFE_FREE(key);
4383         /*
4384          * Get the saved DEVMODE..
4385          */
4386
4387         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4388
4389         /*
4390          * The saved DEVMODE contains the devicename from the printer used during
4391          * the initialization save. Change it to reflect the new printer.
4392          */
4393
4394         if ( info.devmode ) {
4395                 ZERO_STRUCT(info.devmode->devicename);
4396                 fstrcpy(info.devmode->devicename, info_ptr->printername);
4397         }
4398
4399         /*
4400          * NT/2k does not change out the entire DeviceMode of a printer
4401          * when changing the driver.  Only the driverextra, private, &
4402          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
4403          *
4404          * Later examination revealed that Windows NT/2k does reset the
4405          * the printer's device mode, bit **only** when you change a
4406          * property of the device mode such as the page orientation.
4407          * --jerry
4408          */
4409
4410
4411         /* Bind the saved DEVMODE to the new the printer */
4412
4413         free_nt_devicemode(&info_ptr->devmode);
4414         info_ptr->devmode = info.devmode;
4415
4416         DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4417                 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4418
4419         /* Add the printer data 'values' to the new printer */
4420
4421         if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4422                 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4423                 return False;
4424         }
4425
4426         len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4427
4428         SAFE_FREE(dbuf.dptr);
4429
4430         return true;
4431 }
4432
4433 /****************************************************************************
4434  Initialize printer devmode & data with previously saved driver init values.
4435  When a printer is created using AddPrinter, the drivername bound to the
4436  printer is used to lookup previously saved driver initialization info, which
4437  is bound to the new printer.
4438 ****************************************************************************/
4439
4440 bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4441 {
4442         bool result = False;
4443
4444         switch (level) {
4445                 case 2:
4446                         result = set_driver_init_2(printer->info_2);
4447                         break;
4448
4449                 default:
4450                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
4451                                 level));
4452                         break;
4453         }
4454
4455         return result;
4456 }
4457
4458 /****************************************************************************
4459  Delete driver init data stored for a specified driver
4460 ****************************************************************************/
4461
4462 bool del_driver_init(const char *drivername)
4463 {
4464         char *key;
4465         bool ret;
4466
4467         if (!drivername || !*drivername) {
4468                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4469                 return false;
4470         }
4471
4472         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, drivername) < 0) {
4473                 return false;
4474         }
4475
4476         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n",
4477                                 drivername));
4478
4479         ret = (tdb_delete_bystring(tdb_drivers, key) == 0);
4480         SAFE_FREE(key);
4481         return ret;
4482 }
4483
4484 /****************************************************************************
4485  Pack up the DEVMODE and values for a printer into a 'driver init' entry
4486  in the tdb. Note: this is different from the driver entry and the printer
4487  entry. There should be a single driver init entry for each driver regardless
4488  of whether it was installed from NT or 2K. Technically, they should be
4489  different, but they work out to the same struct.
4490 ****************************************************************************/
4491
4492 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4493 {
4494         char *key = NULL;
4495         uint8 *buf;
4496         int buflen, len, ret;
4497         int retlen;
4498         TDB_DATA dbuf;
4499
4500         buf = NULL;
4501         buflen = 0;
4502
4503  again:
4504         len = 0;
4505         len += pack_devicemode(info->devmode, buf+len, buflen-len);
4506
4507         retlen = pack_values( info->data, buf+len, buflen-len );
4508         if (retlen == -1) {
4509                 ret = -1;
4510                 goto done;
4511         }
4512         len += retlen;
4513
4514         if (buflen < len) {
4515                 buf = (uint8 *)SMB_REALLOC(buf, len);
4516                 if (!buf) {
4517                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4518                         ret = -1;
4519                         goto done;
4520                 }
4521                 buflen = len;
4522                 goto again;
4523         }
4524
4525         SAFE_FREE(key);
4526         if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, info->drivername) < 0) {
4527                 ret = (uint32)-1;
4528                 goto done;
4529         }
4530
4531         dbuf.dptr = buf;
4532         dbuf.dsize = len;
4533
4534         ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4535
4536 done:
4537         if (ret == -1)
4538                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4539
4540         SAFE_FREE(buf);
4541
4542         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4543                  info->sharename, info->drivername));
4544
4545         return ret;
4546 }
4547
4548 /****************************************************************************
4549  Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4550 ****************************************************************************/
4551
4552 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4553 {
4554         uint32 result;
4555
4556         dump_a_printer(printer, level);
4557
4558         switch (level) {
4559                 case 2:
4560                         result = update_driver_init_2(printer->info_2);
4561                         break;
4562                 default:
4563                         result = 1;
4564                         break;
4565         }
4566
4567         return result;
4568 }
4569
4570 /****************************************************************************
4571  Convert the printer data value, a REG_BINARY array, into an initialization
4572  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4573  got to keep the endians happy :).
4574 ****************************************************************************/
4575
4576 static bool convert_driver_init(TALLOC_CTX *mem_ctx, NT_DEVICEMODE *nt_devmode,
4577                                 const uint8_t *data, uint32_t data_len)
4578 {
4579         struct spoolss_DeviceMode devmode;
4580         enum ndr_err_code ndr_err;
4581         DATA_BLOB blob;
4582
4583         ZERO_STRUCT(devmode);
4584
4585         blob = data_blob_const(data, data_len);
4586
4587         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &devmode,
4588                         (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
4589         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4590                 DEBUG(10,("convert_driver_init: error parsing spoolss_DeviceMode\n"));
4591                 return false;
4592         }
4593
4594         return convert_devicemode("", &devmode, &nt_devmode);
4595 }
4596
4597 /****************************************************************************
4598  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4599
4600  1. Use the driver's config DLL to this UNC printername and:
4601     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4602     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4603  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4604
4605  The last step triggers saving the "driver initialization" information for
4606  this printer into the tdb. Later, new printers that use this driver will
4607  have this initialization information bound to them. This simulates the
4608  driver initialization, as if it had run on the Samba server (as it would
4609  have done on NT).
4610
4611  The Win32 client side code requirement sucks! But until we can run arbitrary
4612  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4613
4614  It would have been easier to use SetPrinter because all the UNMARSHALLING of
4615  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4616  about it and you will realize why.  JRR 010720
4617 ****************************************************************************/
4618
4619 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4620 {
4621         WERROR        status       = WERR_OK;
4622         TALLOC_CTX    *ctx         = NULL;
4623         NT_DEVICEMODE *nt_devmode  = NULL;
4624         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4625
4626         /*
4627          * When the DEVMODE is already set on the printer, don't try to unpack it.
4628          */
4629         DEBUG(8,("save_driver_init_2: Enter...\n"));
4630
4631         if ( !printer->info_2->devmode && data_len ) {
4632                 /*
4633                  * Set devmode on printer info, so entire printer initialization can be
4634                  * saved to tdb.
4635                  */
4636
4637                 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4638                         return WERR_NOMEM;
4639
4640                 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4641                         status = WERR_NOMEM;
4642                         goto done;
4643                 }
4644
4645                 ZERO_STRUCTP(nt_devmode);
4646
4647                 /*
4648                  * The DEVMODE is held in the 'data' component of the param in raw binary.
4649                  * Convert it to to a devmode structure
4650                  */
4651                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4652                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4653                         status = WERR_INVALID_PARAM;
4654                         goto done;
4655                 }
4656
4657                 printer->info_2->devmode = nt_devmode;
4658         }
4659
4660         /*
4661          * Pack up and add (or update) the DEVMODE and any current printer data to
4662          * a 'driver init' element in the tdb
4663          *
4664          */
4665
4666         if ( update_driver_init(printer, 2) != 0 ) {
4667                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4668                 status = WERR_NOMEM;
4669                 goto done;
4670         }
4671
4672         /*
4673          * If driver initialization info was successfully saved, set the current
4674          * printer to match it. This allows initialization of the current printer
4675          * as well as the driver.
4676          */
4677         status = mod_a_printer(printer, 2);
4678         if (!W_ERROR_IS_OK(status)) {
4679                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4680                                   printer->info_2->printername));
4681         }
4682
4683   done:
4684         talloc_destroy(ctx);
4685         free_nt_devicemode( &nt_devmode );
4686
4687         printer->info_2->devmode = tmp_devmode;
4688
4689         return status;
4690 }
4691
4692 /****************************************************************************
4693  Update the driver init info (DEVMODE and specifics) for a printer
4694 ****************************************************************************/
4695
4696 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4697 {
4698         WERROR status = WERR_OK;
4699
4700         switch (level) {
4701                 case 2:
4702                         status = save_driver_init_2( printer, data, data_len );
4703                         break;
4704                 default:
4705                         status = WERR_UNKNOWN_LEVEL;
4706                         break;
4707         }
4708
4709         return status;
4710 }
4711
4712 /****************************************************************************
4713  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4714
4715  Previously the code had a memory allocation problem because it always
4716  used the TALLOC_CTX from the Printer_entry*.   This context lasts
4717  as a long as the original handle is open.  So if the client made a lot
4718  of getprinter[data]() calls, the memory usage would climb.  Now we use
4719  a short lived TALLOC_CTX for printer_info_2 objects returned.  We
4720  still use the Printer_entry->ctx for maintaining the cache copy though
4721  since that object must live as long as the handle by definition.
4722                                                     --jerry
4723
4724 ****************************************************************************/
4725
4726 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4727                         const char *sharename, bool get_loc_com)
4728 {
4729         WERROR result;
4730         fstring servername;
4731
4732         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4733
4734         if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4735                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4736                 return WERR_NOMEM;
4737         }
4738
4739         switch (level) {
4740                 case 2:
4741                         if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4742                                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4743                                 TALLOC_FREE( *pp_printer );
4744                                 return WERR_NOMEM;
4745                         }
4746
4747                         if ( print_hnd )
4748                                 fstrcpy( servername, print_hnd->servername );
4749                         else {
4750                                 fstrcpy( servername, "%L" );
4751                                 standard_sub_basic( "", "", servername,
4752                                                     sizeof(servername)-1 );
4753                         }
4754
4755                         result = get_a_printer_2( (*pp_printer)->info_2,
4756                                         servername, sharename, get_loc_com);
4757
4758                         /* we have a new printer now.  Save it with this handle */
4759
4760                         if ( !W_ERROR_IS_OK(result) ) {
4761                                 TALLOC_FREE( *pp_printer );
4762                                 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4763                                         sharename, (unsigned int)level, win_errstr(result)));
4764                                 return result;
4765                         }
4766
4767                         dump_a_printer( *pp_printer, level);
4768
4769                         break;
4770
4771                 default:
4772                         TALLOC_FREE( *pp_printer );
4773                         return WERR_UNKNOWN_LEVEL;
4774         }
4775
4776         return WERR_OK;
4777 }
4778
4779 WERROR get_a_printer( Printer_entry *print_hnd,
4780                         NT_PRINTER_INFO_LEVEL **pp_printer,
4781                         uint32 level,
4782                         const char *sharename)
4783 {
4784         return get_a_printer_internal(print_hnd, pp_printer, level,
4785                                         sharename, true);
4786 }
4787
4788 WERROR get_a_printer_search( Printer_entry *print_hnd,
4789                         NT_PRINTER_INFO_LEVEL **pp_printer,
4790                         uint32 level,
4791                         const char *sharename)
4792 {
4793         return get_a_printer_internal(print_hnd, pp_printer, level,
4794                                         sharename, false);
4795 }
4796
4797 /****************************************************************************
4798  Deletes a NT_PRINTER_INFO_LEVEL struct.
4799 ****************************************************************************/
4800
4801 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4802 {
4803         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4804
4805         if ( !printer )
4806                 return 0;
4807
4808         switch (level) {
4809                 case 2:
4810                         if ( printer->info_2 )
4811                                 free_nt_printer_info_level_2(&printer->info_2);
4812                         break;
4813
4814                 default:
4815                         DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4816                         return 1;
4817         }
4818
4819         TALLOC_FREE(*pp_printer);
4820
4821         return 0;
4822 }
4823
4824 /****************************************************************************
4825 ****************************************************************************/
4826
4827 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
4828                               struct spoolss_DriverInfo8 *_info8)
4829 {
4830         struct spoolss_DriverInfo8 info8;
4831
4832         ZERO_STRUCT(info8);
4833
4834         switch (r->level) {
4835         case 3:
4836                 info8.version           = r->info.info3->version;
4837                 info8.driver_name       = r->info.info3->driver_name;
4838                 info8.architecture      = r->info.info3->architecture;
4839                 info8.driver_path       = r->info.info3->driver_path;
4840                 info8.data_file         = r->info.info3->data_file;
4841                 info8.config_file       = r->info.info3->config_file;
4842                 info8.help_file         = r->info.info3->help_file;
4843                 info8.monitor_name      = r->info.info3->monitor_name;
4844                 info8.default_datatype  = r->info.info3->default_datatype;
4845                 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
4846                         info8.dependent_files   = r->info.info3->dependent_files->string;
4847                 }
4848                 break;
4849         case 6:
4850                 info8.version           = r->info.info6->version;
4851                 info8.driver_name       = r->info.info6->driver_name;
4852                 info8.architecture      = r->info.info6->architecture;
4853                 info8.driver_path       = r->info.info6->driver_path;
4854                 info8.data_file         = r->info.info6->data_file;
4855                 info8.config_file       = r->info.info6->config_file;
4856                 info8.help_file         = r->info.info6->help_file;
4857                 info8.monitor_name      = r->info.info6->monitor_name;
4858                 info8.default_datatype  = r->info.info6->default_datatype;
4859                 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
4860                         info8.dependent_files   = r->info.info6->dependent_files->string;
4861                 }
4862                 info8.driver_date       = r->info.info6->driver_date;
4863                 info8.driver_version    = r->info.info6->driver_version;
4864                 info8.manufacturer_name = r->info.info6->manufacturer_name;
4865                 info8.manufacturer_url  = r->info.info6->manufacturer_url;
4866                 info8.hardware_id       = r->info.info6->hardware_id;
4867                 info8.provider          = r->info.info6->provider;
4868                 break;
4869         case 8:
4870                 info8.version           = r->info.info8->version;
4871                 info8.driver_name       = r->info.info8->driver_name;
4872                 info8.architecture      = r->info.info8->architecture;
4873                 info8.driver_path       = r->info.info8->driver_path;
4874                 info8.data_file         = r->info.info8->data_file;
4875                 info8.config_file       = r->info.info8->config_file;
4876                 info8.help_file         = r->info.info8->help_file;
4877                 info8.monitor_name      = r->info.info8->monitor_name;
4878                 info8.default_datatype  = r->info.info8->default_datatype;
4879                 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
4880                         info8.dependent_files   = r->info.info8->dependent_files->string;
4881                 }
4882                 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
4883                         info8.previous_names    = r->info.info8->previous_names->string;
4884                 }
4885                 info8.driver_date       = r->info.info8->driver_date;
4886                 info8.driver_version    = r->info.info8->driver_version;
4887                 info8.manufacturer_name = r->info.info8->manufacturer_name;
4888                 info8.manufacturer_url  = r->info.info8->manufacturer_url;
4889                 info8.hardware_id       = r->info.info8->hardware_id;
4890                 info8.provider          = r->info.info8->provider;
4891                 info8.print_processor   = r->info.info8->print_processor;
4892                 info8.vendor_setup      = r->info.info8->vendor_setup;
4893                 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
4894                         info8.color_profiles = r->info.info8->color_profiles->string;
4895                 }
4896                 info8.inf_path          = r->info.info8->inf_path;
4897                 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
4898                 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
4899                         info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
4900                 }
4901                 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
4902                 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
4903                 break;
4904         default:
4905                 return false;
4906         }
4907
4908         *_info8 = info8;
4909
4910         return true;
4911 }
4912
4913
4914 uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx,
4915                               struct spoolss_AddDriverInfoCtr *r,
4916                               char **driver_name,
4917                               uint32_t *version)
4918 {
4919         struct spoolss_DriverInfo8 info8;
4920
4921         ZERO_STRUCT(info8);
4922
4923         DEBUG(10,("adding a printer at level [%d]\n", r->level));
4924
4925         if (!driver_info_ctr_to_info8(r, &info8)) {
4926                 return -1;
4927         }
4928
4929         *driver_name = talloc_strdup(mem_ctx, info8.driver_name);
4930         if (!*driver_name) {
4931                 return -1;
4932         }
4933         *version = info8.version;
4934
4935         return add_a_printer_driver_8(&info8);
4936 }
4937
4938 /****************************************************************************
4939 ****************************************************************************/
4940
4941 WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx,
4942                             struct spoolss_DriverInfo8 **driver,
4943                             const char *drivername, const char *architecture,
4944                             uint32_t version)
4945 {
4946         WERROR result;
4947         struct spoolss_DriverInfo3 info3;
4948         struct spoolss_DriverInfo8 *info8;
4949
4950         ZERO_STRUCT(info3);
4951
4952         /* Sometime we just want any version of the driver */
4953
4954         if (version == DRIVER_ANY_VERSION) {
4955                 /* look for Win2k first and then for NT4 */
4956                 result = get_a_printer_driver_3(mem_ctx,
4957                                                 &info3,
4958                                                 drivername,
4959                                                 architecture, 3);
4960                 if (!W_ERROR_IS_OK(result)) {
4961                         result = get_a_printer_driver_3(mem_ctx,
4962                                                         &info3,
4963                                                         drivername,
4964                                                         architecture, 2);
4965                 }
4966         } else {
4967                 result = get_a_printer_driver_3(mem_ctx,
4968                                                 &info3,
4969                                                 drivername,
4970                                                 architecture,
4971                                                 version);
4972         }
4973
4974         if (!W_ERROR_IS_OK(result)) {
4975                 return result;
4976         }
4977
4978         info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8);
4979         if (!info8) {
4980                 return WERR_NOMEM;
4981         }
4982
4983         info8->version          = info3.version;
4984         info8->driver_name      = info3.driver_name;
4985         info8->architecture     = info3.architecture;
4986         info8->driver_path      = info3.driver_path;
4987         info8->data_file        = info3.data_file;
4988         info8->config_file      = info3.config_file;
4989         info8->help_file        = info3.help_file;
4990         info8->dependent_files  = info3.dependent_files;
4991         info8->monitor_name     = info3.monitor_name;
4992         info8->default_datatype = info3.default_datatype;
4993
4994         *driver = info8;
4995
4996         return WERR_OK;
4997 }
4998
4999 /****************************************************************************
5000 ****************************************************************************/
5001
5002 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver)
5003 {
5004         talloc_free(driver);
5005         return 0;
5006 }
5007
5008
5009 /****************************************************************************
5010   Determine whether or not a particular driver is currently assigned
5011   to a printer
5012 ****************************************************************************/
5013
5014 bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r)
5015 {
5016         int snum;
5017         int n_services = lp_numservices();
5018         NT_PRINTER_INFO_LEVEL *printer = NULL;
5019         bool in_use = False;
5020
5021         if (!r) {
5022                 return false;
5023         }
5024
5025         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
5026
5027         /* loop through the printers.tdb and check for the drivername */
5028
5029         for (snum=0; snum<n_services && !in_use; snum++) {
5030                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
5031                         continue;
5032
5033                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
5034                         continue;
5035
5036                 if (strequal(r->driver_name, printer->info_2->drivername))
5037                         in_use = True;
5038
5039                 free_a_printer( &printer, 2 );
5040         }
5041
5042         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
5043
5044         if ( in_use ) {
5045                 struct spoolss_DriverInfo8 *d;
5046                 WERROR werr;
5047
5048                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
5049
5050                 /* we can still remove the driver if there is one of
5051                    "Windows NT x86" version 2 or 3 left */
5052
5053                 if (!strequal("Windows NT x86", r->architecture)) {
5054                         werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION);
5055                 }
5056                 else {
5057                         switch (r->version) {
5058                         case 2:
5059                                 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3);
5060                                 break;
5061                         case 3:
5062                                 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2);
5063                                 break;
5064                         default:
5065                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
5066                                         r->version));
5067                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
5068                                 break;
5069                         }
5070                 }
5071
5072                 /* now check the error code */
5073
5074                 if ( W_ERROR_IS_OK(werr) ) {
5075                         /* it's ok to remove the driver, we have other architctures left */
5076                         in_use = False;
5077                         free_a_printer_driver(d);
5078                 }
5079         }
5080
5081         /* report that the driver is not in use by default */
5082
5083         return in_use;
5084 }
5085
5086
5087 /**********************************************************************
5088  Check to see if a ogiven file is in use by *info
5089  *********************************************************************/
5090
5091 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
5092 {
5093         int i = 0;
5094
5095         if ( !info )
5096                 return False;
5097
5098         /* mz: skip files that are in the list but already deleted */
5099         if (!file || !file[0]) {
5100                 return false;
5101         }
5102
5103         if (strequal(file, info->driver_path))
5104                 return True;
5105
5106         if (strequal(file, info->data_file))
5107                 return True;
5108
5109         if (strequal(file, info->config_file))
5110                 return True;
5111
5112         if (strequal(file, info->help_file))
5113                 return True;
5114
5115         /* see of there are any dependent files to examine */
5116
5117         if (!info->dependent_files)
5118                 return False;
5119
5120         while (info->dependent_files[i] && *info->dependent_files[i]) {
5121                 if (strequal(file, info->dependent_files[i]))
5122                         return True;
5123                 i++;
5124         }
5125
5126         return False;
5127
5128 }
5129
5130 /**********************************************************************
5131  Utility function to remove the dependent file pointed to by the
5132  input parameter from the list
5133  *********************************************************************/
5134
5135 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
5136 {
5137
5138         /* bump everything down a slot */
5139
5140         while (files && files[idx+1]) {
5141                 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
5142                 idx++;
5143         }
5144
5145         files[idx] = NULL;
5146
5147         return;
5148 }
5149
5150 /**********************************************************************
5151  Check if any of the files used by src are also used by drv
5152  *********************************************************************/
5153
5154 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
5155                                    struct spoolss_DriverInfo8 *src,
5156                                    const struct spoolss_DriverInfo8 *drv)
5157 {
5158         bool    in_use = False;
5159         int     i = 0;
5160
5161         if ( !src || !drv )
5162                 return False;
5163
5164         /* check each file.  Remove it from the src structure if it overlaps */
5165
5166         if (drv_file_in_use(src->driver_path, drv)) {
5167                 in_use = True;
5168                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
5169                 src->driver_path = talloc_strdup(mem_ctx, "");
5170                 if (!src->driver_path) { return false; }
5171         }
5172
5173         if (drv_file_in_use(src->data_file, drv)) {
5174                 in_use = True;
5175                 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
5176                 src->data_file = talloc_strdup(mem_ctx, "");
5177                 if (!src->data_file) { return false; }
5178         }
5179
5180         if (drv_file_in_use(src->config_file, drv)) {
5181                 in_use = True;
5182                 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
5183                 src->config_file = talloc_strdup(mem_ctx, "");
5184                 if (!src->config_file) { return false; }
5185         }
5186
5187         if (drv_file_in_use(src->help_file, drv)) {
5188                 in_use = True;
5189                 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
5190                 src->help_file = talloc_strdup(mem_ctx, "");
5191                 if (!src->help_file) { return false; }
5192         }
5193
5194         /* are there any dependentfiles to examine? */
5195
5196         if (!src->dependent_files)
5197                 return in_use;
5198
5199         while (src->dependent_files[i] && *src->dependent_files[i]) {
5200                 if (drv_file_in_use(src->dependent_files[i], drv)) {
5201                         in_use = True;
5202                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
5203                         trim_dependent_file(mem_ctx, src->dependent_files, i);
5204                 } else
5205                         i++;
5206         }
5207
5208         return in_use;
5209 }
5210
5211 /****************************************************************************
5212   Determine whether or not a particular driver files are currently being
5213   used by any other driver.
5214
5215   Return value is True if any files were in use by other drivers
5216   and False otherwise.
5217
5218   Upon return, *info has been modified to only contain the driver files
5219   which are not in use
5220
5221   Fix from mz:
5222
5223   This needs to check all drivers to ensure that all files in use
5224   have been removed from *info, not just the ones in the first
5225   match.
5226 ****************************************************************************/
5227
5228 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
5229                                  struct spoolss_DriverInfo8 *info)
5230 {
5231         int                             i;
5232         int                             ndrivers;
5233         uint32                          version;
5234         fstring                         *list = NULL;
5235         struct spoolss_DriverInfo8      *driver;
5236         bool in_use = false;
5237
5238         if ( !info )
5239                 return False;
5240
5241         version = info->version;
5242
5243         /* loop over all driver versions */
5244
5245         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
5246
5247         /* get the list of drivers */
5248
5249         list = NULL;
5250         ndrivers = get_ntdrivers(&list, info->architecture, version);
5251
5252         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
5253                 ndrivers, info->architecture, version));
5254
5255         /* check each driver for overlap in files */
5256
5257         for (i=0; i<ndrivers; i++) {
5258                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5259
5260                 driver = NULL;
5261
5262                 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, list[i], info->architecture, version))) {
5263                         SAFE_FREE(list);
5264                         return True;
5265                 }
5266
5267                 /* check if d2 uses any files from d1 */
5268                 /* only if this is a different driver than the one being deleted */
5269
5270                 if (!strequal(info->driver_name, driver->driver_name)) {
5271                         if (trim_overlap_drv_files(mem_ctx, info, driver)) {
5272                                 /* mz: Do not instantly return -
5273                                  * we need to ensure this file isn't
5274                                  * also in use by other drivers. */
5275                                 in_use = true;
5276                         }
5277                 }
5278
5279                 free_a_printer_driver(driver);
5280         }
5281
5282         SAFE_FREE(list);
5283
5284         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5285
5286         return in_use;
5287 }
5288
5289 static NTSTATUS driver_unlink_internals(connection_struct *conn,
5290                                         const char *name)
5291 {
5292         struct smb_filename *smb_fname = NULL;
5293         NTSTATUS status;
5294
5295         status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
5296             &smb_fname);
5297         if (!NT_STATUS_IS_OK(status)) {
5298                 return status;
5299         }
5300
5301         status = unlink_internals(conn, NULL, 0, smb_fname, false);
5302
5303         TALLOC_FREE(smb_fname);
5304         return status;
5305 }
5306
5307 /****************************************************************************
5308   Actually delete the driver files.  Make sure that
5309   printer_driver_files_in_use() return False before calling
5310   this.
5311 ****************************************************************************/
5312
5313 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
5314                                 const struct spoolss_DriverInfo8 *r)
5315 {
5316         int i = 0;
5317         char *s;
5318         const char *file;
5319         connection_struct *conn;
5320         NTSTATUS nt_status;
5321         char *oldcwd;
5322         fstring printdollar;
5323         int printdollar_snum;
5324         bool ret = false;
5325
5326         if (!r) {
5327                 return false;
5328         }
5329
5330         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
5331                 r->driver_name, r->version));
5332
5333         fstrcpy(printdollar, "print$");
5334
5335         printdollar_snum = find_service(printdollar);
5336         if (printdollar_snum == -1) {
5337                 return false;
5338         }
5339
5340         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5341                                        lp_pathname(printdollar_snum),
5342                                        rpc_pipe->server_info, &oldcwd);
5343         if (!NT_STATUS_IS_OK(nt_status)) {
5344                 DEBUG(0,("delete_driver_files: create_conn_struct "
5345                          "returned %s\n", nt_errstr(nt_status)));
5346                 return false;
5347         }
5348
5349         if ( !CAN_WRITE(conn) ) {
5350                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5351                 goto fail;
5352         }
5353
5354         /* now delete the files; must strip the '\print$' string from
5355            fron of path                                                */
5356
5357         if (r->driver_path && r->driver_path[0]) {
5358                 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
5359                         file = s;
5360                         DEBUG(10,("deleting driverfile [%s]\n", s));
5361                         driver_unlink_internals(conn, file);
5362                 }
5363         }
5364
5365         if (r->config_file && r->config_file[0]) {
5366                 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
5367                         file = s;
5368                         DEBUG(10,("deleting configfile [%s]\n", s));
5369                         driver_unlink_internals(conn, file);
5370                 }
5371         }
5372
5373         if (r->data_file && r->data_file[0]) {
5374                 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
5375                         file = s;
5376                         DEBUG(10,("deleting datafile [%s]\n", s));
5377                         driver_unlink_internals(conn, file);
5378                 }
5379         }
5380
5381         if (r->help_file && r->help_file[0]) {
5382                 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
5383                         file = s;
5384                         DEBUG(10,("deleting helpfile [%s]\n", s));
5385                         driver_unlink_internals(conn, file);
5386                 }
5387         }
5388
5389         /* check if we are done removing files */
5390
5391         if (r->dependent_files) {
5392                 while (r->dependent_files[i] && r->dependent_files[i][0]) {
5393                         char *p;
5394
5395                         /* bypass the "\print$" portion of the path */
5396
5397                         if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
5398                                 file = p;
5399                                 DEBUG(10,("deleting dependent file [%s]\n", file));
5400                                 driver_unlink_internals(conn, file);
5401                         }
5402
5403                         i++;
5404                 }
5405         }
5406
5407         goto done;
5408  fail:
5409         ret = false;
5410  done:
5411         if (conn != NULL) {
5412                 vfs_ChDir(conn, oldcwd);
5413                 conn_free(conn);
5414         }
5415         return ret;
5416 }
5417
5418 /****************************************************************************
5419  Remove a printer driver from the TDB.  This assumes that the the driver was
5420  previously looked up.
5421  ***************************************************************************/
5422
5423 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5424                              const struct spoolss_DriverInfo8 *r,
5425                              uint32 version, bool delete_files )
5426 {
5427         char *key = NULL;
5428         const char     *arch;
5429         TDB_DATA        dbuf;
5430
5431         /* delete the tdb data first */
5432
5433         arch = get_short_archi(r->architecture);
5434         if (!arch) {
5435                 return WERR_UNKNOWN_PRINTER_DRIVER;
5436         }
5437         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5438                         arch, version, r->driver_name) < 0) {
5439                 return WERR_NOMEM;
5440         }
5441
5442         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5443                 key, delete_files ? "TRUE" : "FALSE" ));
5444
5445         /* check if the driver actually exists for this environment */
5446
5447         dbuf = tdb_fetch_bystring( tdb_drivers, key );
5448         if ( !dbuf.dptr ) {
5449                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5450                 SAFE_FREE(key);
5451                 return WERR_UNKNOWN_PRINTER_DRIVER;
5452         }
5453
5454         SAFE_FREE( dbuf.dptr );
5455
5456         /* ok... the driver exists so the delete should return success */
5457
5458         if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5459                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5460                 SAFE_FREE(key);
5461                 return WERR_ACCESS_DENIED;
5462         }
5463
5464         /*
5465          * now delete any associated files if delete_files == True
5466          * even if this part failes, we return succes because the
5467          * driver doesn not exist any more
5468          */
5469
5470         if ( delete_files )
5471                 delete_driver_files(rpc_pipe, r);
5472
5473         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5474         SAFE_FREE(key);
5475
5476         return WERR_OK;
5477 }
5478
5479 /****************************************************************************
5480  Store a security desc for a printer.
5481 ****************************************************************************/
5482
5483 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
5484 {
5485         struct sec_desc_buf *new_secdesc_ctr = NULL;
5486         struct sec_desc_buf *old_secdesc_ctr = NULL;
5487         TALLOC_CTX *mem_ctx = NULL;
5488         TDB_DATA kbuf;
5489         TDB_DATA dbuf;
5490         DATA_BLOB blob;
5491         WERROR status;
5492         NTSTATUS nt_status;
5493
5494         mem_ctx = talloc_init("nt_printing_setsec");
5495         if (mem_ctx == NULL)
5496                 return WERR_NOMEM;
5497
5498         /* The old owner and group sids of the security descriptor are not
5499            present when new ACEs are added or removed by changing printer
5500            permissions through NT.  If they are NULL in the new security
5501            descriptor then copy them over from the old one. */
5502
5503         if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5504                 DOM_SID *owner_sid, *group_sid;
5505                 struct security_acl *dacl, *sacl;
5506                 struct security_descriptor *psd = NULL;
5507                 size_t size;
5508
5509                 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5510                         status = WERR_NOMEM;
5511                         goto out;
5512                 }
5513
5514                 /* Pick out correct owner and group sids */
5515
5516                 owner_sid = secdesc_ctr->sd->owner_sid ?
5517                         secdesc_ctr->sd->owner_sid :
5518                         old_secdesc_ctr->sd->owner_sid;
5519
5520                 group_sid = secdesc_ctr->sd->group_sid ?
5521                         secdesc_ctr->sd->group_sid :
5522                         old_secdesc_ctr->sd->group_sid;
5523
5524                 dacl = secdesc_ctr->sd->dacl ?
5525                         secdesc_ctr->sd->dacl :
5526                         old_secdesc_ctr->sd->dacl;
5527
5528                 sacl = secdesc_ctr->sd->sacl ?
5529                         secdesc_ctr->sd->sacl :
5530                         old_secdesc_ctr->sd->sacl;
5531
5532                 /* Make a deep copy of the security descriptor */
5533
5534                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5535                                     owner_sid, group_sid,
5536                                     sacl,
5537                                     dacl,
5538                                     &size);
5539
5540                 if (!psd) {
5541                         status = WERR_NOMEM;
5542                         goto out;
5543                 }
5544
5545                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5546         }
5547
5548         if (!new_secdesc_ctr) {
5549                 new_secdesc_ctr = secdesc_ctr;
5550         }
5551
5552         /* Store the security descriptor in a tdb */
5553
5554         nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5555                                           &blob.data, &blob.length);
5556         if (!NT_STATUS_IS_OK(nt_status)) {
5557                 status = ntstatus_to_werror(nt_status);
5558                 goto out;
5559         }
5560
5561         kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5562
5563         dbuf.dptr = (unsigned char *)blob.data;
5564         dbuf.dsize = blob.length;
5565
5566         if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5567                 status = WERR_OK;
5568         } else {
5569                 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5570                 status = WERR_BADFUNC;
5571         }
5572
5573         /* Free malloc'ed memory */
5574         talloc_free(blob.data);
5575
5576  out:
5577
5578         if (mem_ctx)
5579                 talloc_destroy(mem_ctx);
5580         return status;
5581 }
5582
5583 /****************************************************************************
5584  Construct a default security descriptor buffer for a printer.
5585 ****************************************************************************/
5586
5587 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
5588 {
5589         struct security_ace ace[5];     /* max number of ace entries */
5590         int i = 0;
5591         uint32_t sa;
5592         struct security_acl *psa = NULL;
5593         struct sec_desc_buf *sdb = NULL;
5594         struct security_descriptor *psd = NULL;
5595         DOM_SID adm_sid;
5596         size_t sd_size;
5597
5598         /* Create an ACE where Everyone is allowed to print */
5599
5600         sa = PRINTER_ACE_PRINT;
5601         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5602                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5603
5604         /* Add the domain admins group if we are a DC */
5605
5606         if ( IS_DC ) {
5607                 DOM_SID domadmins_sid;
5608
5609                 sid_compose(&domadmins_sid, get_global_sam_sid(),
5610                             DOMAIN_RID_ADMINS);
5611
5612                 sa = PRINTER_ACE_FULL_CONTROL;
5613                 init_sec_ace(&ace[i++], &domadmins_sid,
5614                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5615                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5616                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5617                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5618         }
5619         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5620                 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
5621
5622                 sa = PRINTER_ACE_FULL_CONTROL;
5623                 init_sec_ace(&ace[i++], &adm_sid,
5624                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5625                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5626                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5627                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5628         }
5629
5630         /* add BUILTIN\Administrators as FULL CONTROL */
5631
5632         sa = PRINTER_ACE_FULL_CONTROL;
5633         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5634                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5635                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5636         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5637                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5638                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5639
5640         /* Make the security descriptor owned by the BUILTIN\Administrators */
5641
5642         /* The ACL revision number in rpc_secdesc.h differs from the one
5643            created by NT when setting ACE entries in printer
5644            descriptors.  NT4 complains about the property being edited by a
5645            NT5 machine. */
5646
5647         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5648                 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
5649                         &global_sid_Builtin_Administrators,
5650                         &global_sid_Builtin_Administrators,
5651                         NULL, psa, &sd_size);
5652         }
5653
5654         if (!psd) {
5655                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5656                 return NULL;
5657         }
5658
5659         sdb = make_sec_desc_buf(ctx, sd_size, psd);
5660
5661         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5662                  (unsigned int)sd_size));
5663
5664         return sdb;
5665 }
5666
5667 /****************************************************************************
5668  Get a security desc for a printer.
5669 ****************************************************************************/
5670
5671 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
5672 {
5673         TDB_DATA kbuf;
5674         TDB_DATA dbuf;
5675         DATA_BLOB blob;
5676         char *temp;
5677         NTSTATUS status;
5678
5679         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5680                 sharename = temp + 1;
5681         }
5682
5683         /* Fetch security descriptor from tdb */
5684
5685         kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5686
5687         dbuf = tdb_fetch(tdb_printers, kbuf);
5688         if (dbuf.dptr) {
5689
5690                 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5691                                                  secdesc_ctr);
5692                 SAFE_FREE(dbuf.dptr);
5693
5694                 if (NT_STATUS_IS_OK(status)) {
5695                         return true;
5696                 }
5697         }
5698
5699         *secdesc_ctr = construct_default_printer_sdb(ctx);
5700         if (!*secdesc_ctr) {
5701                 return false;
5702         }
5703
5704         status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5705                                        &blob.data, &blob.length);
5706         if (NT_STATUS_IS_OK(status)) {
5707                 dbuf.dptr = (unsigned char *)blob.data;
5708                 dbuf.dsize = blob.length;
5709                 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5710                 talloc_free(blob.data);
5711         }
5712
5713         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5714            this security descriptor has been created when winbindd was
5715            down.  Take ownership of security descriptor. */
5716
5717         if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5718                 DOM_SID owner_sid;
5719
5720                 /* Change sd owner to workgroup administrator */
5721
5722                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5723                         struct sec_desc_buf *new_secdesc_ctr = NULL;
5724                         struct security_descriptor *psd = NULL;
5725                         size_t size;
5726
5727                         /* Create new sd */
5728
5729                         sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
5730
5731                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5732                                             &owner_sid,
5733                                             (*secdesc_ctr)->sd->group_sid,
5734                                             (*secdesc_ctr)->sd->sacl,
5735                                             (*secdesc_ctr)->sd->dacl,
5736                                             &size);
5737
5738                         if (!psd) {
5739                                 return False;
5740                         }
5741
5742                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5743                         if (!new_secdesc_ctr) {
5744                                 return False;
5745                         }
5746
5747                         /* Swap with other one */
5748
5749                         *secdesc_ctr = new_secdesc_ctr;
5750
5751                         /* Set it */
5752
5753                         nt_printing_setsec(sharename, *secdesc_ctr);
5754                 }
5755         }
5756
5757         if (DEBUGLEVEL >= 10) {
5758                 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
5759                 int i;
5760
5761                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5762                            sharename, the_acl->num_aces));
5763
5764                 for (i = 0; i < the_acl->num_aces; i++) {
5765                         DEBUG(10, ("%s %d %d 0x%08x\n",
5766                                    sid_string_dbg(&the_acl->aces[i].trustee),
5767                                    the_acl->aces[i].type, the_acl->aces[i].flags,
5768                                    the_acl->aces[i].access_mask));
5769                 }
5770         }
5771
5772         return True;
5773 }
5774
5775 /* error code:
5776         0: everything OK
5777         1: level not implemented
5778         2: file doesn't exist
5779         3: can't allocate memory
5780         4: can't free memory
5781         5: non existant struct
5782 */
5783
5784 /*
5785         A printer and a printer driver are 2 different things.
5786         NT manages them separatelly, Samba does the same.
5787         Why ? Simply because it's easier and it makes sense !
5788
5789         Now explanation: You have 3 printers behind your samba server,
5790         2 of them are the same make and model (laser A and B). But laser B
5791         has an 3000 sheet feeder and laser A doesn't such an option.
5792         Your third printer is an old dot-matrix model for the accounting :-).
5793
5794         If the /usr/local/samba/lib directory (default dir), you will have
5795         5 files to describe all of this.
5796
5797         3 files for the printers (1 by printer):
5798                 NTprinter_laser A
5799                 NTprinter_laser B
5800                 NTprinter_accounting
5801         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5802                 NTdriver_printer model X
5803                 NTdriver_printer model Y
5804
5805 jfm: I should use this comment for the text file to explain
5806         same thing for the forms BTW.
5807         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5808
5809 */
5810
5811 /* Convert generic access rights to printer object specific access rights.
5812    It turns out that NT4 security descriptors use generic access rights and
5813    NT5 the object specific ones. */
5814
5815 void map_printer_permissions(struct security_descriptor *sd)
5816 {
5817         int i;
5818
5819         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5820                 se_map_generic(&sd->dacl->aces[i].access_mask,
5821                                &printer_generic_mapping);
5822         }
5823 }
5824
5825 void map_job_permissions(struct security_descriptor *sd)
5826 {
5827         int i;
5828
5829         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5830                 se_map_generic(&sd->dacl->aces[i].access_mask,
5831                                &job_generic_mapping);
5832         }
5833 }
5834
5835
5836 /****************************************************************************
5837  Check a user has permissions to perform the given operation.  We use the
5838  permission constants defined in include/rpc_spoolss.h to check the various
5839  actions we perform when checking printer access.
5840
5841    PRINTER_ACCESS_ADMINISTER:
5842        print_queue_pause, print_queue_resume, update_printer_sec,
5843        update_printer, spoolss_addprinterex_level_2,
5844        _spoolss_setprinterdata
5845
5846    PRINTER_ACCESS_USE:
5847        print_job_start
5848
5849    JOB_ACCESS_ADMINISTER:
5850        print_job_delete, print_job_pause, print_job_resume,
5851        print_queue_purge
5852
5853   Try access control in the following order (for performance reasons):
5854     1)  root and SE_PRINT_OPERATOR can do anything (easy check)
5855     2)  check security descriptor (bit comparisons in memory)
5856     3)  "printer admins" (may result in numerous calls to winbind)
5857
5858  ****************************************************************************/
5859 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5860                         int access_type)
5861 {
5862         struct sec_desc_buf *secdesc = NULL;
5863         uint32 access_granted;
5864         NTSTATUS status;
5865         const char *pname;
5866         TALLOC_CTX *mem_ctx = NULL;
5867         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5868
5869         /* If user is NULL then use the current_user structure */
5870
5871         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5872
5873         if (server_info->utok.uid == sec_initial_uid()
5874             || user_has_privileges(server_info->ptok, &se_printop ) ) {
5875                 return True;
5876         }
5877
5878         /* Get printer name */
5879
5880         pname = PRINTERNAME(snum);
5881
5882         if (!pname || !*pname) {
5883                 errno = EACCES;
5884                 return False;
5885         }
5886
5887         /* Get printer security descriptor */
5888
5889         if(!(mem_ctx = talloc_init("print_access_check"))) {
5890                 errno = ENOMEM;
5891                 return False;
5892         }
5893
5894         if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5895                 talloc_destroy(mem_ctx);
5896                 errno = ENOMEM;
5897                 return False;
5898         }
5899
5900         if (access_type == JOB_ACCESS_ADMINISTER) {
5901                 struct sec_desc_buf *parent_secdesc = secdesc;
5902
5903                 /* Create a child security descriptor to check permissions
5904                    against.  This is because print jobs are child objects
5905                    objects of a printer. */
5906
5907                 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5908
5909                 if (!NT_STATUS_IS_OK(status)) {
5910                         talloc_destroy(mem_ctx);
5911                         errno = map_errno_from_nt_status(status);
5912                         return False;
5913                 }
5914
5915                 map_job_permissions(secdesc->sd);
5916         } else {
5917                 map_printer_permissions(secdesc->sd);
5918         }
5919
5920         /* Check access */
5921         status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5922                                  &access_granted);
5923
5924         DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5925
5926         /* see if we need to try the printer admin list */
5927
5928         if (!NT_STATUS_IS_OK(status) &&
5929             (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5930                                          NULL, NULL, server_info->ptok,
5931                                          lp_printer_admin(snum)))) {
5932                 talloc_destroy(mem_ctx);
5933                 return True;
5934         }
5935
5936         talloc_destroy(mem_ctx);
5937
5938         if (!NT_STATUS_IS_OK(status)) {
5939                 errno = EACCES;
5940         }
5941
5942         return NT_STATUS_IS_OK(status);
5943 }
5944
5945 /****************************************************************************
5946  Check the time parameters allow a print operation.
5947 *****************************************************************************/
5948
5949 bool print_time_access_check(const char *servicename)
5950 {
5951         NT_PRINTER_INFO_LEVEL *printer = NULL;
5952         bool ok = False;
5953         time_t now = time(NULL);
5954         struct tm *t;
5955         uint32 mins;
5956
5957         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5958                 return False;
5959
5960         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5961                 ok = True;
5962
5963         t = gmtime(&now);
5964         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5965
5966         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5967                 ok = True;
5968
5969         free_a_printer(&printer, 2);
5970
5971         if (!ok)
5972                 errno = EACCES;
5973
5974         return ok;
5975 }
5976
5977 /****************************************************************************
5978  Fill in the servername sent in the _spoolss_open_printer_ex() call
5979 ****************************************************************************/
5980
5981 char* get_server_name( Printer_entry *printer )
5982 {
5983         return printer->servername;
5984 }
5985
5986