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