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