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