Fix from Martin Zielinski <mz@seh.de>. Don't delete files when
[samba.git] / source / 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 extern struct current_user current_user;
25
26 static TDB_CONTEXT *tdb_forms; /* used for forms files */
27 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
28 static TDB_CONTEXT *tdb_printers; /* used for printers files */
29
30 #define FORMS_PREFIX "FORMS/"
31 #define DRIVERS_PREFIX "DRIVERS/"
32 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
33 #define PRINTERS_PREFIX "PRINTERS/"
34 #define SECDESC_PREFIX "SECDESC/"
35 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
36  
37 #define NTDRIVERS_DATABASE_VERSION_1 1
38 #define NTDRIVERS_DATABASE_VERSION_2 2
39 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
40 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
41 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
42
43 /* Map generic permissions to printer object specific permissions */
44
45 const struct generic_mapping printer_generic_mapping = {
46         PRINTER_READ,
47         PRINTER_WRITE,
48         PRINTER_EXECUTE,
49         PRINTER_ALL_ACCESS
50 };
51
52 const struct standard_mapping printer_std_mapping = {
53         PRINTER_READ,
54         PRINTER_WRITE,
55         PRINTER_EXECUTE,
56         PRINTER_ALL_ACCESS
57 };
58
59 /* Map generic permissions to print server object specific permissions */
60
61 const struct generic_mapping printserver_generic_mapping = {
62         SERVER_READ,
63         SERVER_WRITE,
64         SERVER_EXECUTE,
65         SERVER_ALL_ACCESS
66 };
67
68 const struct generic_mapping printserver_std_mapping = {
69         SERVER_READ,
70         SERVER_WRITE,
71         SERVER_EXECUTE,
72         SERVER_ALL_ACCESS
73 };
74
75 /* We need one default form to support our default printer. Msoft adds the
76 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
77 array index). Letter is always first, so (for the current code) additions
78 always put things in the correct order. */
79 static const nt_forms_struct default_forms[] = {
80         {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
81         {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82         {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
83         {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
84         {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
85         {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
86         {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
87         {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
88         {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
89         {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90         {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
91         {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
92         {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
93         {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
94         {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
95         {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
96         {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
97         {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
98         {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
99         {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
100         {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
101         {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
102         {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
103         {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
104         {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
105         {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
106         {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
107         {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
108         {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
109         {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
110         {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
111         {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
112         {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
113         {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
114         {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
115         {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
116         {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
117         {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
118         {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
119         {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
120         {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
121         {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
122         {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
123         {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
124         {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
125         {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
126         {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
127         {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
128         {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129         {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
130         {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
131         {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
132         {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
133         {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
134         {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
135         {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
136         {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
137         {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
138         {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
139         {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
140         {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
141         {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
142         {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
143         {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
144         {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
145         {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
146         {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
147         {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
148         {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
149         {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
150         {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
151         {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
152         {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
153         {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
154         {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
155         {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
156         {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
157         {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
158         {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
159         {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
160         {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
161         {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
162         {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
163         {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
164         {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
165         {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
166         {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
167         {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
168         {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
169         {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
170         {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
171         {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
172         {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
173         {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
174         {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
175         {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
176         {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
177         {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
178         {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
179         {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
180         {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
181         {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
182         {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
183         {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
184         {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
185         {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
186         {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
187         {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
188         {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
189         {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
190         {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
191         {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
192         {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
193         {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
194         {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
195         {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
196         {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
197         {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
198 };
199
200 struct table_node {
201         const char      *long_archi;
202         const char      *short_archi;
203         int     version;
204 };
205  
206 #define SPL_ARCH_WIN40          "WIN40"
207 #define SPL_ARCH_W32X86         "W32X86"
208 #define SPL_ARCH_W32MIPS        "W32MIPS"
209 #define SPL_ARCH_W32ALPHA       "W32ALPHA"
210 #define SPL_ARCH_W32PPC         "W32PPC"
211 #define SPL_ARCH_IA64           "IA64"
212 #define SPL_ARCH_X64            "x64"
213
214 static const struct table_node archi_table[]= {
215
216         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
217         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
218         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
219         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
220         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
221         {"Windows IA64",         SPL_ARCH_IA64,         3 },
222         {"Windows x64",          SPL_ARCH_X64,          3 },
223         {NULL,                   "",            -1 }
224 };
225
226
227 /****************************************************************************
228  generate a new TDB_DATA key for storing a printer
229 ****************************************************************************/
230
231 static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
232 {
233         fstring share;
234         char *keystr = NULL;
235         TDB_DATA key;
236
237         fstrcpy(share, sharename);
238         strlower_m(share);
239
240         keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
241         key = string_term_tdb_data(keystr ? keystr : "");
242
243         return key;
244 }
245
246 /****************************************************************************
247  generate a new TDB_DATA key for storing a printer security descriptor
248 ****************************************************************************/
249
250 static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
251                                         const char* sharename  )
252 {
253         fstring share;
254         char *keystr = NULL;
255         TDB_DATA key;
256
257         fstrcpy(share, sharename );
258         strlower_m(share);
259
260         keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
261         key = string_term_tdb_data(keystr ? keystr : "");
262
263         return key;
264 }
265
266 /****************************************************************************
267 ****************************************************************************/
268
269 static bool upgrade_to_version_3(void)
270 {
271         TDB_DATA kbuf, newkey, dbuf;
272  
273         DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
274  
275         for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
276                         newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
277
278                 dbuf = tdb_fetch(tdb_drivers, kbuf);
279
280                 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
281                         DEBUG(0,("upgrade_to_version_3:moving form\n"));
282                         if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
283                                 SAFE_FREE(dbuf.dptr);
284                                 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
285                                 return False;
286                         }
287                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
288                                 SAFE_FREE(dbuf.dptr);
289                                 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
290                                 return False;
291                         }
292                 }
293  
294                 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
295                         DEBUG(0,("upgrade_to_version_3:moving printer\n"));
296                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
297                                 SAFE_FREE(dbuf.dptr);
298                                 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
299                                 return False;
300                         }
301                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
302                                 SAFE_FREE(dbuf.dptr);
303                                 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
304                                 return False;
305                         }
306                 }
307  
308                 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
309                         DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
310                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
311                                 SAFE_FREE(dbuf.dptr);
312                                 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
313                                 return False;
314                         }
315                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
316                                 SAFE_FREE(dbuf.dptr);
317                                 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
318                                 return False;
319                         }
320                 }
321  
322                 SAFE_FREE(dbuf.dptr);
323         }
324
325         return True;
326 }
327
328 /*******************************************************************
329  Fix an issue with security descriptors.  Printer sec_desc must 
330  use more than the generic bits that were previously used 
331  in <= 3.0.14a.  They must also have a owner and group SID assigned.
332  Otherwise, any printers than have been migrated to a Windows 
333  host using printmig.exe will not be accessible.
334 *******************************************************************/
335
336 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
337                             TDB_DATA data, void *state )
338 {
339         prs_struct ps;
340         SEC_DESC_BUF *sd_orig = NULL;
341         SEC_DESC_BUF *sd_new, *sd_store;
342         SEC_DESC *sec, *new_sec;
343         TALLOC_CTX *ctx = state;
344         int result, i;
345         uint32 sd_size;
346         size_t size_new_sec;
347
348         if (!data.dptr || data.dsize == 0) {
349                 return 0;
350         }
351
352         if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
353                 return 0;
354         }
355
356         /* upgrade the security descriptor */
357
358         ZERO_STRUCT( ps );
359
360         prs_init_empty( &ps, ctx, UNMARSHALL );
361         prs_give_memory( &ps, (char *)data.dptr, data.dsize, False );
362
363         if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
364                 /* delete bad entries */
365                 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si.  Deleting....\n",
366                         (const char *)key.dptr ));
367                 tdb_delete( tdb_printers, key );
368                 prs_mem_free( &ps );
369                 return 0;
370         }
371
372         if (!sd_orig) {
373                 prs_mem_free( &ps );
374                 return 0;
375         }
376         sec = sd_orig->sd;
377                 
378         /* is this even valid? */
379         
380         if ( !sec->dacl ) {
381                 prs_mem_free( &ps );
382                 return 0;
383         }
384                 
385         /* update access masks */
386         
387         for ( i=0; i<sec->dacl->num_aces; i++ ) {
388                 switch ( sec->dacl->aces[i].access_mask ) {
389                         case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
390                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
391                                 break;
392                                 
393                         case GENERIC_ALL_ACCESS:
394                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
395                                 break;
396                                 
397                         case READ_CONTROL_ACCESS:
398                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
399                         
400                         default:        /* no change */
401                                 break;
402                 }
403         }
404
405         /* create a new SEC_DESC with the appropriate owner and group SIDs */
406
407         new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
408                                  &global_sid_Builtin_Administrators,
409                                  &global_sid_Builtin_Administrators,
410                                  NULL, NULL, &size_new_sec );
411         if (!new_sec) {
412                 prs_mem_free( &ps );
413                 return 0;
414         }
415         sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
416         if (!sd_new) {
417                 prs_mem_free( &ps );
418                 return 0;
419         }
420
421         if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
422                 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
423                 prs_mem_free( &ps );
424                 return 0;
425         }
426         
427         prs_mem_free( &ps );
428
429         /* store it back */
430         
431         sd_size = ndr_size_security_descriptor(sd_store->sd, 0)
432                 + sizeof(SEC_DESC_BUF);
433         if ( !prs_init(&ps, sd_size, ctx, MARSHALL) ) {
434                 DEBUG(0,("sec_desc_upg_fn: Failed to allocate prs memory for %s\n", key.dptr ));
435                 return 0;
436         }
437
438         if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
439                 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
440                 prs_mem_free( &ps );
441                 return 0;
442         }
443
444         data.dptr = (uint8 *)prs_data_p( &ps );
445         data.dsize = sd_size;
446         
447         result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
448
449         prs_mem_free( &ps );
450         
451         /* 0 to continue and non-zero to stop traversal */
452
453         return (result == -1);
454 }
455
456 /*******************************************************************
457 *******************************************************************/
458
459 static bool upgrade_to_version_4(void)
460 {
461         TALLOC_CTX *ctx;
462         int result;
463
464         DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
465
466         if ( !(ctx = talloc_init( "upgrade_to_version_4" )) ) 
467                 return False;
468
469         result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
470
471         talloc_destroy( ctx );
472
473         return ( result != -1 );
474 }
475
476 /*******************************************************************
477  Fix an issue with security descriptors.  Printer sec_desc must 
478  use more than the generic bits that were previously used 
479  in <= 3.0.14a.  They must also have a owner and group SID assigned.
480  Otherwise, any printers than have been migrated to a Windows 
481  host using printmig.exe will not be accessible.
482 *******************************************************************/
483
484 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
485                                   TDB_DATA data, void *state )
486 {
487         TALLOC_CTX *ctx = talloc_tos();
488         TDB_DATA new_key;
489
490         if (!data.dptr || data.dsize == 0)
491                 return 0;
492
493         /* upgrade printer records and security descriptors */
494
495         if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
496                 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
497         }
498         else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
499                 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
500         }
501         else {
502                 /* ignore this record */
503                 return 0;
504         }
505
506         /* delete the original record and store under the normalized key */
507
508         if ( tdb_delete( the_tdb, key ) != 0 ) {
509                 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n", 
510                         key.dptr));
511                 return 1;
512         }
513
514         if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
515                 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
516                         key.dptr));
517                 return 1;
518         }
519
520         return 0;
521 }
522
523 /*******************************************************************
524 *******************************************************************/
525
526 static bool upgrade_to_version_5(void)
527 {
528         TALLOC_CTX *ctx;
529         int result;
530
531         DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
532
533         if ( !(ctx = talloc_init( "upgrade_to_version_5" )) ) 
534                 return False;
535
536         result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
537
538         talloc_destroy( ctx );
539
540         return ( result != -1 );
541 }
542
543 /****************************************************************************
544  Open the NT printing tdbs. Done once before fork().
545 ****************************************************************************/
546
547 bool nt_printing_init(struct messaging_context *msg_ctx)
548 {
549         const char *vstring = "INFO/version";
550         WERROR win_rc;
551         int32 vers_id;
552
553         if ( tdb_drivers && tdb_printers && tdb_forms )
554                 return True;
555  
556         if (tdb_drivers)
557                 tdb_close(tdb_drivers);
558         tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
559         if (!tdb_drivers) {
560                 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
561                         state_path("ntdrivers.tdb"), strerror(errno) ));
562                 return False;
563         }
564  
565         if (tdb_printers)
566                 tdb_close(tdb_printers);
567         tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
568         if (!tdb_printers) {
569                 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
570                         state_path("ntprinters.tdb"), strerror(errno) ));
571                 return False;
572         }
573  
574         if (tdb_forms)
575                 tdb_close(tdb_forms);
576         tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
577         if (!tdb_forms) {
578                 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
579                         state_path("ntforms.tdb"), strerror(errno) ));
580                 return False;
581         }
582  
583         /* handle a Samba upgrade */
584         
585         vers_id = tdb_fetch_int32(tdb_drivers, vstring);
586         if (vers_id == -1) {
587                 DEBUG(10, ("Fresh database\n"));
588                 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
589                 vers_id = NTDRIVERS_DATABASE_VERSION_5;
590         }
591
592         if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
593
594                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) { 
595                         if (!upgrade_to_version_3())
596                                 return False;
597                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
598                         vers_id = NTDRIVERS_DATABASE_VERSION_3;
599                 } 
600                 
601                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
602                         /* Written on a bigendian machine with old fetch_int code. Save as le. */
603                         /* The only upgrade between V2 and V3 is to save the version in little-endian. */
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_3 ) {
609                         if ( !upgrade_to_version_4() )
610                                 return False;
611                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
612                         vers_id = NTDRIVERS_DATABASE_VERSION_4;
613                 }
614
615                 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
616                         if ( !upgrade_to_version_5() )
617                                 return False;
618                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
619                         vers_id = NTDRIVERS_DATABASE_VERSION_5;
620                 }
621
622
623                 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
624                         DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
625                         return False;
626                 }
627         }
628         
629         update_c_setprinter(True);
630
631         /*
632          * register callback to handle updating printers as new
633          * drivers are installed
634          */
635
636         messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
637                            do_drv_upgrade_printer);
638
639         /*
640          * register callback to handle updating printer data
641          * when a driver is initialized
642          */
643
644         messaging_register(msg_ctx, NULL, MSG_PRINTERDATA_INIT_RESET,
645                            reset_all_printerdata);
646
647         /* of course, none of the message callbacks matter if you don't
648            tell messages.c that you interested in receiving PRINT_GENERAL 
649            msgs.  This is done in claim_connection() */
650
651
652         if ( lp_security() == SEC_ADS ) {
653                 win_rc = check_published_printers();
654                 if (!W_ERROR_IS_OK(win_rc))
655                         DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
656         }
657
658         return True;
659 }
660
661 /*******************************************************************
662  Function to allow filename parsing "the old way".
663 ********************************************************************/
664
665 static char *driver_unix_convert(connection_struct *conn,
666                 const char *old_name,
667                 SMB_STRUCT_STAT *pst)
668 {
669         TALLOC_CTX *ctx = talloc_tos();
670         char *name = talloc_strdup(ctx, old_name);
671         char *new_name = NULL;
672
673         if (!name) {
674                 return NULL;
675         }
676         unix_format(name);
677         name = unix_clean_name(ctx, name);
678         if (!name) {
679                 return NULL;
680         }
681         trim_string(name,"/","/");
682         unix_convert(ctx,conn, name, false, &new_name, NULL, pst);
683         return new_name;
684 }
685
686 /*******************************************************************
687  tdb traversal function for counting printers.
688 ********************************************************************/
689
690 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
691                                       TDB_DATA data, void *context)
692 {
693         int *printer_count = (int*)context;
694  
695         if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
696                 (*printer_count)++;
697                 DEBUG(10,("traverse_counting_printers: printer = [%s]  printer_count = %d\n", key.dptr, *printer_count));
698         }
699  
700         return 0;
701 }
702  
703 /*******************************************************************
704  Update the spooler global c_setprinter. This variable is initialized
705  when the parent smbd starts with the number of existing printers. It
706  is monotonically increased by the current number of printers *after*
707  each add or delete printer RPC. Only Microsoft knows why... JRR020119
708 ********************************************************************/
709
710 uint32 update_c_setprinter(bool initialize)
711 {
712         int32 c_setprinter;
713         int32 printer_count = 0;
714  
715         tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
716  
717         /* Traverse the tdb, counting the printers */
718         tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
719  
720         /* If initializing, set c_setprinter to current printers count
721          * otherwise, bump it by the current printer count
722          */
723         if (!initialize)
724                 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
725         else
726                 c_setprinter = printer_count;
727  
728         DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
729         tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
730  
731         tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
732  
733         return (uint32)c_setprinter;
734 }
735
736 /*******************************************************************
737  Get the spooler global c_setprinter, accounting for initialization.
738 ********************************************************************/
739
740 uint32 get_c_setprinter(void)
741 {
742         int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
743  
744         if (c_setprinter == (int32)-1)
745                 c_setprinter = update_c_setprinter(True);
746  
747         DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
748  
749         return (uint32)c_setprinter;
750 }
751
752 /****************************************************************************
753  Get builtin form struct list.
754 ****************************************************************************/
755
756 int get_builtin_ntforms(nt_forms_struct **list)
757 {
758         *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
759         if (!*list) {
760                 return 0;
761         }
762         return sizeof(default_forms) / sizeof(default_forms[0]);
763 }
764
765 /****************************************************************************
766  get a builtin form struct
767 ****************************************************************************/
768
769 bool get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
770 {
771         int i,count;
772         fstring form_name;
773         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
774         DEBUGADD(6,("Looking for builtin form %s \n", form_name));
775         count = sizeof(default_forms) / sizeof(default_forms[0]);
776         for (i=0;i<count;i++) {
777                 if (strequal(form_name,default_forms[i].name)) {
778                         DEBUGADD(6,("Found builtin form %s \n", form_name));
779                         memcpy(form,&default_forms[i],sizeof(*form));
780                         break;
781                 }
782         }
783
784         return (i !=count);
785 }
786
787 /****************************************************************************
788  get a form struct list.
789 ****************************************************************************/
790
791 int get_ntforms(nt_forms_struct **list)
792 {
793         TDB_DATA kbuf, newkey, dbuf;
794         nt_forms_struct form;
795         int ret;
796         int i;
797         int n = 0;
798
799         *list = NULL;
800
801         for (kbuf = tdb_firstkey(tdb_forms);
802              kbuf.dptr;
803              newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) 
804         {
805                 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) 
806                         continue;
807                 
808                 dbuf = tdb_fetch(tdb_forms, kbuf);
809                 if (!dbuf.dptr) 
810                         continue;
811
812                 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
813                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
814                                  &i, &form.flag, &form.width, &form.length, &form.left,
815                                  &form.top, &form.right, &form.bottom);
816                 SAFE_FREE(dbuf.dptr);
817                 if (ret != dbuf.dsize) 
818                         continue;
819
820                 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
821                 if (!*list) {
822                         DEBUG(0,("get_ntforms: Realloc fail.\n"));
823                         return 0;
824                 }
825                 (*list)[n] = form;
826                 n++;
827         }
828         
829
830         return n;
831 }
832
833 /****************************************************************************
834 write a form struct list
835 ****************************************************************************/
836
837 int write_ntforms(nt_forms_struct **list, int number)
838 {
839         TALLOC_CTX *ctx = talloc_tos();
840         char *buf = NULL;
841         char *key = NULL;
842         int len;
843         TDB_DATA dbuf;
844         int i;
845
846         for (i=0;i<number;i++) {
847                 /* save index, so list is rebuilt in correct order */
848                 len = tdb_pack(NULL, 0, "dddddddd",
849                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
850                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
851                                (*list)[i].bottom);
852                 if (!len) {
853                         continue;
854                 }
855                 buf = TALLOC_ARRAY(ctx, char, len);
856                 if (!buf) {
857                         return 0;
858                 }
859                 len = tdb_pack((uint8 *)buf, len, "dddddddd",
860                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
861                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
862                                (*list)[i].bottom);
863                 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
864                 if (!key) {
865                         return 0;
866                 }
867                 dbuf.dsize = len;
868                 dbuf.dptr = (uint8 *)buf;
869                 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
870                         TALLOC_FREE(key);
871                         TALLOC_FREE(buf);
872                         break;
873                 }
874                 TALLOC_FREE(key);
875                 TALLOC_FREE(buf);
876        }
877
878        return i;
879 }
880
881 /****************************************************************************
882 add a form struct at the end of the list
883 ****************************************************************************/
884 bool add_a_form(nt_forms_struct **list, const FORM *form, int *count)
885 {
886         int n=0;
887         bool update;
888         fstring form_name;
889
890         /*
891          * NT tries to add forms even when
892          * they are already in the base
893          * only update the values if already present
894          */
895
896         update=False;
897         
898         unistr2_to_ascii(form_name, &form->name, sizeof(form_name));
899         for (n=0; n<*count; n++) {
900                 if ( strequal((*list)[n].name, form_name) ) {
901                         update=True;
902                         break;
903                 }
904         }
905
906         if (update==False) {
907                 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
908                         DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
909                         return False;
910                 }
911                 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name));
912                 (*count)++;
913         }
914         
915         (*list)[n].flag=form->flags;
916         (*list)[n].width=form->size_x;
917         (*list)[n].length=form->size_y;
918         (*list)[n].left=form->left;
919         (*list)[n].top=form->top;
920         (*list)[n].right=form->right;
921         (*list)[n].bottom=form->bottom;
922
923         DEBUG(6,("add_a_form: Successfully %s form [%s]\n", 
924                 update ? "updated" : "added", form_name));
925
926         return True;
927 }
928
929 /****************************************************************************
930  Delete a named form struct.
931 ****************************************************************************/
932
933 bool delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
934 {
935         char *key = NULL;
936         int n=0;
937         fstring form_name;
938
939         *ret = WERR_OK;
940
941         unistr2_to_ascii(form_name, del_name, sizeof(form_name));
942
943         for (n=0; n<*count; n++) {
944                 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
945                         DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
946                         break;
947                 }
948         }
949
950         if (n == *count) {
951                 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
952                 *ret = WERR_INVALID_PARAM;
953                 return False;
954         }
955
956         if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
957                 *ret = WERR_NOMEM;
958                 return false;
959         }
960         if (tdb_delete_bystring(tdb_forms, key) != 0) {
961                 SAFE_FREE(key);
962                 *ret = WERR_NOMEM;
963                 return False;
964         }
965         SAFE_FREE(key);
966         return true;
967 }
968
969 /****************************************************************************
970  Update a form struct.
971 ****************************************************************************/
972
973 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
974 {
975         int n=0;
976         fstring form_name;
977         unistr2_to_ascii(form_name, &(form->name), sizeof(form_name));
978
979         DEBUG(106, ("[%s]\n", form_name));
980         for (n=0; n<count; n++) {
981                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
982                 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
983                         break;
984         }
985
986         if (n==count) return;
987
988         (*list)[n].flag=form->flags;
989         (*list)[n].width=form->size_x;
990         (*list)[n].length=form->size_y;
991         (*list)[n].left=form->left;
992         (*list)[n].top=form->top;
993         (*list)[n].right=form->right;
994         (*list)[n].bottom=form->bottom;
995 }
996
997 /****************************************************************************
998  Get the nt drivers list.
999  Traverse the database and look-up the matching names.
1000 ****************************************************************************/
1001 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
1002 {
1003         int total=0;
1004         const char *short_archi;
1005         char *key = NULL;
1006         TDB_DATA kbuf, newkey;
1007
1008         short_archi = get_short_archi(architecture);
1009         if (!short_archi) {
1010                 return 0;
1011         }
1012
1013         if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
1014                                 short_archi, version) < 0) {
1015                 return 0;
1016         }
1017
1018         for (kbuf = tdb_firstkey(tdb_drivers);
1019              kbuf.dptr;
1020              newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
1021
1022                 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
1023                         continue;
1024
1025                 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
1026                         DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
1027                         SAFE_FREE(key);
1028                         return -1;
1029                 }
1030
1031                 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
1032                 total++;
1033         }
1034
1035         SAFE_FREE(key);
1036         return(total);
1037 }
1038
1039 /****************************************************************************
1040  Function to do the mapping between the long architecture name and
1041  the short one.
1042 ****************************************************************************/
1043
1044 const char *get_short_archi(const char *long_archi)
1045 {
1046         int i=-1;
1047
1048         DEBUG(107,("Getting architecture dependant directory\n"));
1049         do {
1050                 i++;
1051         } while ( (archi_table[i].long_archi!=NULL ) &&
1052                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
1053
1054         if (archi_table[i].long_archi==NULL) {
1055                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1056                 return NULL;
1057         }
1058
1059         /* this might be client code - but shouldn't this be an fstrcpy etc? */
1060
1061         DEBUGADD(108,("index: [%d]\n", i));
1062         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1063         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1064
1065         return archi_table[i].short_archi;
1066 }
1067
1068 /****************************************************************************
1069  Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1070  There are two case to be covered here: PE (Portable Executable) and NE (New
1071  Executable) files. Both files support the same INFO structure, but PE files
1072  store the signature in unicode, and NE files store it as !unicode.
1073  returns -1 on error, 1 on version info found, and 0 on no version info found.
1074 ****************************************************************************/
1075
1076 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1077 {
1078         int     i;
1079         char    *buf = NULL;
1080         ssize_t byte_count;
1081
1082         if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1083                 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1084                                 fname, DOS_HEADER_SIZE));
1085                 goto error_exit;
1086         }
1087
1088         if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1089                 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1090                          fname, (unsigned long)byte_count));
1091                 goto no_version_info;
1092         }
1093
1094         /* Is this really a DOS header? */
1095         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1096                 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1097                                 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1098                 goto no_version_info;
1099         }
1100
1101         /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1102         if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1103                 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1104                                 fname, errno));
1105                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1106                 goto no_version_info;
1107         }
1108
1109         /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1110         if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1111                 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1112                          fname, (unsigned long)byte_count));
1113                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1114                 goto no_version_info;
1115         }
1116
1117         /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1118         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1119                 unsigned int num_sections;
1120                 unsigned int section_table_bytes;
1121
1122                 /* Just skip over optional header to get to section table */
1123                 if (SMB_VFS_LSEEK(fsp,
1124                                 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1125                                 SEEK_CUR) == (SMB_OFF_T)-1) {
1126                         DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1127                                 fname, errno));
1128                         goto error_exit;
1129                 }
1130
1131                 /* get the section table */
1132                 num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1133                 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1134                 if (section_table_bytes == 0)
1135                         goto error_exit;
1136
1137                 SAFE_FREE(buf);
1138                 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1139                         DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1140                                         fname, section_table_bytes));
1141                         goto error_exit;
1142                 }
1143
1144                 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1145                         DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1146                                  fname, (unsigned long)byte_count));
1147                         goto error_exit;
1148                 }
1149
1150                 /* Iterate the section table looking for the resource section ".rsrc" */
1151                 for (i = 0; i < num_sections; i++) {
1152                         int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1153
1154                         if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1155                                 unsigned int section_pos   = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1156                                 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1157
1158                                 if (section_bytes == 0)
1159                                         goto error_exit;
1160
1161                                 SAFE_FREE(buf);
1162                                 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1163                                         DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1164                                                         fname, section_bytes));
1165                                         goto error_exit;
1166                                 }
1167
1168                                 /* Seek to the start of the .rsrc section info */
1169                                 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1170                                         DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1171                                                         fname, errno));
1172                                         goto error_exit;
1173                                 }
1174
1175                                 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1176                                         DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1177                                                  fname, (unsigned long)byte_count));
1178                                         goto error_exit;
1179                                 }
1180
1181                                 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1182                                         goto error_exit;
1183
1184                                 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1185                                         /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1186                                         if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1187                                                 /* Align to next long address */
1188                                                 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1189
1190                                                 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1191                                                         *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1192                                                         *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1193
1194                                                         DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1195                                                                           fname, *major, *minor,
1196                                                                           (*major>>16)&0xffff, *major&0xffff,
1197                                                                           (*minor>>16)&0xffff, *minor&0xffff));
1198                                                         SAFE_FREE(buf);
1199                                                         return 1;
1200                                                 }
1201                                         }
1202                                 }
1203                         }
1204                 }
1205
1206                 /* Version info not found, fall back to origin date/time */
1207                 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1208                 SAFE_FREE(buf);
1209                 return 0;
1210
1211         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1212                 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1213                         DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1214                                         fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1215                         /* At this point, we assume the file is in error. It still could be somthing
1216                          * else besides a NE file, but it unlikely at this point. */
1217                         goto error_exit;
1218                 }
1219
1220                 /* Allocate a bit more space to speed up things */
1221                 SAFE_FREE(buf);
1222                 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1223                         DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes  = %d\n",
1224                                         fname, PE_HEADER_SIZE));
1225                         goto error_exit;
1226                 }
1227
1228                 /* This is a HACK! I got tired of trying to sort through the messy
1229                  * 'NE' file format. If anyone wants to clean this up please have at
1230                  * it, but this works. 'NE' files will eventually fade away. JRR */
1231                 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1232                         /* Cover case that should not occur in a well formed 'NE' .dll file */
1233                         if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1234
1235                         for(i=0; i<byte_count; i++) {
1236                                 /* Fast skip past data that can't possibly match */
1237                                 if (buf[i] != 'V') continue;
1238
1239                                 /* Potential match data crosses buf boundry, move it to beginning
1240                                  * of buf, and fill the buf with as much as it will hold. */
1241                                 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1242                                         int bc;
1243
1244                                         memcpy(buf, &buf[i], byte_count-i);
1245                                         if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1246                                                                    (byte_count-i))) < 0) {
1247
1248                                                 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1249                                                                  fname, errno));
1250                                                 goto error_exit;
1251                                         }
1252
1253                                         byte_count = bc + (byte_count - i);
1254                                         if (byte_count<VS_VERSION_INFO_SIZE) break;
1255
1256                                         i = 0;
1257                                 }
1258
1259                                 /* Check that the full signature string and the magic number that
1260                                  * follows exist (not a perfect solution, but the chances that this
1261                                  * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1262                                  * twice, as it is simpler to read the code. */
1263                                 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1264                                         /* Compute skip alignment to next long address */
1265                                         int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1266                                                                  sizeof(VS_SIGNATURE)) & 3;
1267                                         if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1268
1269                                         *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1270                                         *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1271                                         DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1272                                                           fname, *major, *minor,
1273                                                           (*major>>16)&0xffff, *major&0xffff,
1274                                                           (*minor>>16)&0xffff, *minor&0xffff));
1275                                         SAFE_FREE(buf);
1276                                         return 1;
1277                                 }
1278                         }
1279                 }
1280
1281                 /* Version info not found, fall back to origin date/time */
1282                 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1283                 SAFE_FREE(buf);
1284                 return 0;
1285
1286         } else
1287                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1288                 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1289                                 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1290
1291         no_version_info:
1292                 SAFE_FREE(buf);
1293                 return 0;
1294
1295         error_exit:
1296                 SAFE_FREE(buf);
1297                 return -1;
1298 }
1299
1300 /****************************************************************************
1301 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1302 share one or more files. During the MS installation process files are checked
1303 to insure that only a newer version of a shared file is installed over an
1304 older version. There are several possibilities for this comparison. If there
1305 is no previous version, the new one is newer (obviously). If either file is
1306 missing the version info structure, compare the creation date (on Unix use
1307 the modification date). Otherwise chose the numerically larger version number.
1308 ****************************************************************************/
1309
1310 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1311 {
1312         bool use_version = true;
1313         char *filepath = NULL;
1314
1315         uint32 new_major;
1316         uint32 new_minor;
1317         time_t new_create_time;
1318
1319         uint32 old_major;
1320         uint32 old_minor;
1321         time_t old_create_time;
1322
1323         files_struct    *fsp = NULL;
1324         SMB_STRUCT_STAT st;
1325         SMB_STRUCT_STAT stat_buf;
1326
1327         NTSTATUS status;
1328
1329         SET_STAT_INVALID(st);
1330         SET_STAT_INVALID(stat_buf);
1331         new_create_time = (time_t)0;
1332         old_create_time = (time_t)0;
1333
1334         /* Get file version info (if available) for previous file (if it exists) */
1335         filepath = driver_unix_convert(conn,old_file,&stat_buf);
1336         if (!filepath) {
1337                 goto error_exit;
1338         }
1339
1340         status = open_file_ntcreate(conn, NULL, filepath, &stat_buf,
1341                                 FILE_GENERIC_READ,
1342                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1343                                 FILE_OPEN,
1344                                 0,
1345                                 FILE_ATTRIBUTE_NORMAL,
1346                                 INTERNAL_OPEN_ONLY,
1347                                 NULL, &fsp);
1348
1349         if (!NT_STATUS_IS_OK(status)) {
1350                 /* Old file not found, so by definition new file is in fact newer */
1351                 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1352                                 filepath, errno));
1353                 return 1;
1354
1355         } else {
1356                 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1357                 if (ret == -1) {
1358                         goto error_exit;
1359                 }
1360
1361                 if (!ret) {
1362                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1363                                          old_file));
1364                         use_version = false;
1365                         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1366                                  goto error_exit;
1367                         }
1368                         old_create_time = st.st_mtime;
1369                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1370                 }
1371         }
1372         close_file(fsp, NORMAL_CLOSE);
1373
1374         /* Get file version info (if available) for new file */
1375         filepath = driver_unix_convert(conn,new_file,&stat_buf);
1376         if (!filepath) {
1377                 goto error_exit;
1378         }
1379
1380         status = open_file_ntcreate(conn, NULL, filepath, &stat_buf,
1381                                 FILE_GENERIC_READ,
1382                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1383                                 FILE_OPEN,
1384                                 0,
1385                                 FILE_ATTRIBUTE_NORMAL,
1386                                 INTERNAL_OPEN_ONLY,
1387                                 NULL, &fsp);
1388
1389         if (!NT_STATUS_IS_OK(status)) {
1390                 /* New file not found, this shouldn't occur if the caller did its job */
1391                 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1392                                 filepath, errno));
1393                 goto error_exit;
1394
1395         } else {
1396                 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1397                 if (ret == -1) {
1398                         goto error_exit;
1399                 }
1400
1401                 if (!ret) {
1402                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1403                                          new_file));
1404                         use_version = false;
1405                         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1406                                 goto error_exit;
1407                         }
1408                         new_create_time = st.st_mtime;
1409                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1410                 }
1411         }
1412         close_file(fsp, NORMAL_CLOSE);
1413
1414         if (use_version && (new_major != old_major || new_minor != old_minor)) {
1415                 /* Compare versions and choose the larger version number */
1416                 if (new_major > old_major ||
1417                         (new_major == old_major && new_minor > old_minor)) {
1418
1419                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1420                         return 1;
1421                 }
1422                 else {
1423                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1424                         return 0;
1425                 }
1426
1427         } else {
1428                 /* Compare modification time/dates and choose the newest time/date */
1429                 if (new_create_time > old_create_time) {
1430                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1431                         return 1;
1432                 }
1433                 else {
1434                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1435                         return 0;
1436                 }
1437         }
1438
1439         error_exit:
1440                 if(fsp)
1441                         close_file(fsp, NORMAL_CLOSE);
1442                 return -1;
1443 }
1444
1445 /****************************************************************************
1446 Determine the correct cVersion associated with an architecture and driver
1447 ****************************************************************************/
1448 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1449                                    struct current_user *user, WERROR *perr)
1450 {
1451         int               cversion;
1452         NTSTATUS          nt_status;
1453         char *driverpath = NULL;
1454         DATA_BLOB         null_pw;
1455         fstring           res_type;
1456         files_struct      *fsp = NULL;
1457         SMB_STRUCT_STAT   st;
1458         connection_struct *conn;
1459         NTSTATUS status;
1460
1461         SET_STAT_INVALID(st);
1462
1463         *perr = WERR_INVALID_PARAM;
1464
1465         /* If architecture is Windows 95/98/ME, the version is always 0. */
1466         if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1467                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1468                 *perr = WERR_OK;
1469                 return 0;
1470         }
1471
1472         /* If architecture is Windows x64, the version is always 3. */
1473         if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1474                 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1475                 *perr = WERR_OK;
1476                 return 3;
1477         }
1478
1479         /*
1480          * Connect to the print$ share under the same account as the user connected
1481          * to the rpc pipe. Note we must still be root to do this.
1482          */
1483
1484         /* Null password is ok - we are already an authenticated user... */
1485         null_pw = data_blob_null;
1486         fstrcpy(res_type, "A:");
1487         become_root();
1488         conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1489         unbecome_root();
1490
1491         if (conn == NULL) {
1492                 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1493                 *perr = ntstatus_to_werror(nt_status);
1494                 return -1;
1495         }
1496
1497         /* We are temporarily becoming the connection user. */
1498         if (!become_user(conn, user->vuid)) {
1499                 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1500                 *perr = WERR_ACCESS_DENIED;
1501                 return -1;
1502         }
1503
1504         /* Open the driver file (Portable Executable format) and determine the
1505          * deriver the cversion. */
1506         driverpath = talloc_asprintf(talloc_tos(),
1507                                         "%s/%s",
1508                                         architecture,
1509                                         driverpath_in);
1510         if (!driverpath) {
1511                 *perr = WERR_NOMEM;
1512                 goto error_exit;
1513         }
1514
1515         driverpath = driver_unix_convert(conn,driverpath,&st);
1516         if (!driverpath) {
1517                 *perr = WERR_NOMEM;
1518                 goto error_exit;
1519         }
1520
1521         if (!vfs_file_exist(conn, driverpath, &st)) {
1522                 *perr = WERR_BADFILE;
1523                 goto error_exit;
1524         }
1525
1526         status = open_file_ntcreate(conn, NULL, driverpath, &st,
1527                                 FILE_GENERIC_READ,
1528                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1529                                 FILE_OPEN,
1530                                 0,
1531                                 FILE_ATTRIBUTE_NORMAL,
1532                                 INTERNAL_OPEN_ONLY,
1533                                 NULL, &fsp);
1534
1535         if (!NT_STATUS_IS_OK(status)) {
1536                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1537                                 driverpath, errno));
1538                 *perr = WERR_ACCESS_DENIED;
1539                 goto error_exit;
1540         } else {
1541                 uint32 major;
1542                 uint32 minor;
1543                 int    ret = get_file_version(fsp, driverpath, &major, &minor);
1544                 if (ret == -1) goto error_exit;
1545
1546                 if (!ret) {
1547                         DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1548                         goto error_exit;
1549                 }
1550
1551                 /*
1552                  * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1553                  * for more details. Version in this case is not just the version of the 
1554                  * file, but the version in the sense of kernal mode (2) vs. user mode
1555                  * (3) drivers. Other bits of the version fields are the version info. 
1556                  * JRR 010716
1557                 */
1558                 cversion = major & 0x0000ffff;
1559                 switch (cversion) {
1560                         case 2: /* WinNT drivers */
1561                         case 3: /* Win2K drivers */
1562                                 break;
1563                         
1564                         default:
1565                                 DEBUG(6,("get_correct_cversion: cversion invalid [%s]  cversion = %d\n", 
1566                                         driverpath, cversion));
1567                                 goto error_exit;
1568                 }
1569
1570                 DEBUG(10,("get_correct_cversion: Version info found [%s]  major = 0x%x  minor = 0x%x\n",
1571                                   driverpath, major, minor));
1572         }
1573
1574         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1575                 driverpath, cversion));
1576
1577         close_file(fsp, NORMAL_CLOSE);
1578         close_cnum(conn, user->vuid);
1579         unbecome_user();
1580         *perr = WERR_OK;
1581         return cversion;
1582
1583
1584   error_exit:
1585
1586         if(fsp)
1587                 close_file(fsp, NORMAL_CLOSE);
1588
1589         close_cnum(conn, user->vuid);
1590         unbecome_user();
1591         return -1;
1592 }
1593
1594 /****************************************************************************
1595 ****************************************************************************/
1596 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1597                                                                                          struct current_user *user)
1598 {
1599         const char *architecture;
1600         fstring new_name;
1601         char *p;
1602         int i;
1603         WERROR err;
1604
1605         /* clean up the driver name.
1606          * we can get .\driver.dll
1607          * or worse c:\windows\system\driver.dll !
1608          */
1609         /* using an intermediate string to not have overlaping memcpy()'s */
1610         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1611                 fstrcpy(new_name, p+1);
1612                 fstrcpy(driver->driverpath, new_name);
1613         }
1614
1615         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1616                 fstrcpy(new_name, p+1);
1617                 fstrcpy(driver->datafile, new_name);
1618         }
1619
1620         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1621                 fstrcpy(new_name, p+1);
1622                 fstrcpy(driver->configfile, new_name);
1623         }
1624
1625         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1626                 fstrcpy(new_name, p+1);
1627                 fstrcpy(driver->helpfile, new_name);
1628         }
1629
1630         if (driver->dependentfiles) {
1631                 for (i=0; *driver->dependentfiles[i]; i++) {
1632                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1633                                 fstrcpy(new_name, p+1);
1634                                 fstrcpy(driver->dependentfiles[i], new_name);
1635                         }
1636                 }
1637         }
1638
1639         architecture = get_short_archi(driver->environment);
1640         if (!architecture) {
1641                 return WERR_UNKNOWN_PRINTER_DRIVER;
1642         }
1643         
1644         /* jfm:7/16/2000 the client always sends the cversion=0.
1645          * The server should check which version the driver is by reading
1646          * the PE header of driver->driverpath.
1647          *
1648          * For Windows 95/98 the version is 0 (so the value sent is correct)
1649          * For Windows NT (the architecture doesn't matter)
1650          *      NT 3.1: cversion=0
1651          *      NT 3.5/3.51: cversion=1
1652          *      NT 4: cversion=2
1653          *      NT2K: cversion=3
1654          */
1655         if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1656                 return err;
1657
1658         return WERR_OK;
1659 }
1660         
1661 /****************************************************************************
1662 ****************************************************************************/
1663 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1664 {
1665         const char *architecture;
1666         fstring new_name;
1667         char *p;
1668         int i;
1669         WERROR err;
1670
1671         /* clean up the driver name.
1672          * we can get .\driver.dll
1673          * or worse c:\windows\system\driver.dll !
1674          */
1675         /* using an intermediate string to not have overlaping memcpy()'s */
1676         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1677                 fstrcpy(new_name, p+1);
1678                 fstrcpy(driver->driverpath, new_name);
1679         }
1680
1681         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1682                 fstrcpy(new_name, p+1);
1683                 fstrcpy(driver->datafile, new_name);
1684         }
1685
1686         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1687                 fstrcpy(new_name, p+1);
1688                 fstrcpy(driver->configfile, new_name);
1689         }
1690
1691         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1692                 fstrcpy(new_name, p+1);
1693                 fstrcpy(driver->helpfile, new_name);
1694         }
1695
1696         if (driver->dependentfiles) {
1697                 for (i=0; *driver->dependentfiles[i]; i++) {
1698                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1699                                 fstrcpy(new_name, p+1);
1700                                 fstrcpy(driver->dependentfiles[i], new_name);
1701                         }
1702                 }
1703         }
1704
1705         architecture = get_short_archi(driver->environment);
1706         if (!architecture) {
1707                 return WERR_UNKNOWN_PRINTER_DRIVER;
1708         }
1709
1710         /* jfm:7/16/2000 the client always sends the cversion=0.
1711          * The server should check which version the driver is by reading
1712          * the PE header of driver->driverpath.
1713          *
1714          * For Windows 95/98 the version is 0 (so the value sent is correct)
1715          * For Windows NT (the architecture doesn't matter)
1716          *      NT 3.1: cversion=0
1717          *      NT 3.5/3.51: cversion=1
1718          *      NT 4: cversion=2
1719          *      NT2K: cversion=3
1720          */
1721
1722         if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1723                         return err;
1724
1725         return WERR_OK;
1726 }
1727
1728 /****************************************************************************
1729 ****************************************************************************/
1730 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1731                                                           uint32 level, struct current_user *user)
1732 {
1733         switch (level) {
1734                 case 3:
1735                 {
1736                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1737                         driver=driver_abstract.info_3;
1738                         return clean_up_driver_struct_level_3(driver, user);
1739                 }
1740                 case 6:
1741                 {
1742                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1743                         driver=driver_abstract.info_6;
1744                         return clean_up_driver_struct_level_6(driver, user);
1745                 }
1746                 default:
1747                         return WERR_INVALID_PARAM;
1748         }
1749 }
1750
1751 /****************************************************************************
1752  This function sucks and should be replaced. JRA.
1753 ****************************************************************************/
1754
1755 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1756 {
1757     dst->cversion  = src->version;
1758
1759     fstrcpy( dst->name, src->name);
1760     fstrcpy( dst->environment, src->environment);
1761     fstrcpy( dst->driverpath, src->driverpath);
1762     fstrcpy( dst->datafile, src->datafile);
1763     fstrcpy( dst->configfile, src->configfile);
1764     fstrcpy( dst->helpfile, src->helpfile);
1765     fstrcpy( dst->monitorname, src->monitorname);
1766     fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1767     dst->dependentfiles = src->dependentfiles;
1768 }
1769
1770 #if 0 /* Debugging function */
1771
1772 static char* ffmt(unsigned char *c){
1773         int i;
1774         static char ffmt_str[17];
1775
1776         for (i=0; i<16; i++) {
1777                 if ((c[i] < ' ') || (c[i] > '~'))
1778                         ffmt_str[i]='.';
1779                 else
1780                         ffmt_str[i]=c[i];
1781         }
1782     ffmt_str[16]='\0';
1783         return ffmt_str;
1784 }
1785
1786 #endif
1787
1788 /****************************************************************************
1789 ****************************************************************************/
1790 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, 
1791                                   struct current_user *user, WERROR *perr)
1792 {
1793         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1794         NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1795         const char *architecture;
1796         char *new_dir = NULL;
1797         char *old_name = NULL;
1798         char *new_name = NULL;
1799         DATA_BLOB null_pw;
1800         connection_struct *conn;
1801         NTSTATUS nt_status;
1802         fstring res_type;
1803         SMB_STRUCT_STAT st;
1804         int i;
1805         TALLOC_CTX *ctx = talloc_tos();
1806         int ver = 0;
1807
1808         *perr = WERR_OK;
1809
1810         if (level==3)
1811                 driver=driver_abstract.info_3;
1812         else if (level==6) {
1813                 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1814                 driver = &converted_driver;
1815         } else {
1816                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1817                 return WERR_UNKNOWN_LEVEL;
1818         }
1819
1820         architecture = get_short_archi(driver->environment);
1821         if (!architecture) {
1822                 return WERR_UNKNOWN_PRINTER_DRIVER;
1823         }
1824
1825         /*
1826          * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1827          * Note we must be root to do this.
1828          */
1829
1830         null_pw = data_blob_null;
1831         fstrcpy(res_type, "A:");
1832         become_root();
1833         conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1834         unbecome_root();
1835
1836         if (conn == NULL) {
1837                 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1838                 *perr = ntstatus_to_werror(nt_status);
1839                 return WERR_NO_SUCH_SHARE;
1840         }
1841
1842         /*
1843          * Save who we are - we are temporarily becoming the connection user.
1844          */
1845
1846         if (!become_user(conn, conn->vuid)) {
1847                 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1848                 return WERR_ACCESS_DENIED;
1849         }
1850
1851         /* WE ARE NOW RUNNING AS USER conn->vuid !!!!! */
1852
1853         /*
1854          * make the directories version and version\driver_name
1855          * under the architecture directory.
1856          */
1857         DEBUG(5,("Creating first directory\n"));
1858         new_dir = talloc_asprintf(ctx,
1859                                 "%s/%d",
1860                                 architecture,
1861                                 driver->cversion);
1862         if (!new_dir) {
1863                 *perr = WERR_NOMEM;
1864                 goto err_exit;
1865         }
1866         new_dir = driver_unix_convert(conn,new_dir,&st);
1867         if (!new_dir) {
1868                 *perr = WERR_NOMEM;
1869                 goto err_exit;
1870         }
1871
1872         create_directory(conn, NULL, new_dir);
1873
1874         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1875          * listed for this driver which has already been moved, skip it (note:
1876          * drivers may list the same file name several times. Then check if the
1877          * file already exists in archi\cversion\, if so, check that the version
1878          * info (or time stamps if version info is unavailable) is newer (or the
1879          * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1880          * Otherwise, delete the file.
1881          *
1882          * If a file is not moved to archi\cversion\ because of an error, all the
1883          * rest of the 'unmoved' driver files are removed from archi\. If one or
1884          * more of the driver's files was already moved to archi\cversion\, it
1885          * potentially leaves the driver in a partially updated state. Version
1886          * trauma will most likely occur if an client attempts to use any printer
1887          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1888          * done is appropriate... later JRR
1889          */
1890
1891         DEBUG(5,("Moving files now !\n"));
1892
1893         if (driver->driverpath && strlen(driver->driverpath)) {
1894                 new_name = talloc_asprintf(ctx,
1895                                         "%s/%s",
1896                                         architecture,
1897                                         driver->driverpath);
1898                 if (!new_name) {
1899                         *perr = WERR_NOMEM;
1900                         goto err_exit;
1901                 }
1902                 old_name = talloc_asprintf(ctx,
1903                                         "%s/%s",
1904                                         new_dir,
1905                                         driver->driverpath);
1906                 if (!old_name) {
1907                         *perr = WERR_NOMEM;
1908                         goto err_exit;
1909                 }
1910
1911                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1912                         new_name = driver_unix_convert(conn,new_name,&st);
1913                         if (!new_name) {
1914                                 *perr = WERR_NOMEM;
1915                                 goto err_exit;
1916                         }
1917                         if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1918                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1919                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1920                                                 new_name, old_name));
1921                                 *perr = WERR_ACCESS_DENIED;
1922                                 ver = -1;
1923                         }
1924                 }
1925         }
1926
1927         if (driver->datafile && strlen(driver->datafile)) {
1928                 if (!strequal(driver->datafile, driver->driverpath)) {
1929                         new_name = talloc_asprintf(ctx,
1930                                         "%s/%s",
1931                                         architecture,
1932                                         driver->datafile);
1933                         if (!new_name) {
1934                                 *perr = WERR_NOMEM;
1935                                 goto err_exit;
1936                         }
1937                         old_name = talloc_asprintf(ctx,
1938                                         "%s/%s",
1939                                         new_dir,
1940                                         driver->datafile);
1941                         if (!old_name) {
1942                                 *perr = WERR_NOMEM;
1943                                 goto err_exit;
1944                         }
1945                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1946                                 new_name = driver_unix_convert(conn,new_name,&st);
1947                                 if (!new_name) {
1948                                         *perr = WERR_NOMEM;
1949                                         goto err_exit;
1950                                 }
1951                                 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1952                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1953                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1954                                                         new_name, old_name));
1955                                         *perr = WERR_ACCESS_DENIED;
1956                                         ver = -1;
1957                                 }
1958                         }
1959                 }
1960         }
1961
1962         if (driver->configfile && strlen(driver->configfile)) {
1963                 if (!strequal(driver->configfile, driver->driverpath) &&
1964                         !strequal(driver->configfile, driver->datafile)) {
1965                         new_name = talloc_asprintf(ctx,
1966                                                 "%s/%s",
1967                                                 architecture,
1968                                                 driver->configfile);
1969                         if (!new_name) {
1970                                 *perr = WERR_NOMEM;
1971                                 goto err_exit;
1972                         }
1973                         old_name = talloc_asprintf(ctx,
1974                                                 "%s/%s",
1975                                                 new_dir,
1976                                                 driver->configfile);
1977                         if (!old_name) {
1978                                 *perr = WERR_NOMEM;
1979                                 goto err_exit;
1980                         }
1981                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1982                                 new_name = driver_unix_convert(conn,new_name,&st);
1983                                 if (!new_name) {
1984                                         *perr = WERR_NOMEM;
1985                                         goto err_exit;
1986                                 }
1987                                 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1988                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1989                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1990                                                         new_name, old_name));
1991                                         *perr = WERR_ACCESS_DENIED;
1992                                         ver = -1;
1993                                 }
1994                         }
1995                 }
1996         }
1997
1998         if (driver->helpfile && strlen(driver->helpfile)) {
1999                 if (!strequal(driver->helpfile, driver->driverpath) &&
2000                         !strequal(driver->helpfile, driver->datafile) &&
2001                         !strequal(driver->helpfile, driver->configfile)) {
2002                         new_name = talloc_asprintf(ctx,
2003                                         "%s/%s",
2004                                         architecture,
2005                                         driver->helpfile);
2006                         if (!new_name) {
2007                                 *perr = WERR_NOMEM;
2008                                 goto err_exit;
2009                         }
2010                         old_name = talloc_asprintf(ctx,
2011                                         "%s/%s",
2012                                         new_dir,
2013                                         driver->helpfile);
2014                         if (!old_name) {
2015                                 *perr = WERR_NOMEM;
2016                                 goto err_exit;
2017                         }
2018                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
2019                                 new_name = driver_unix_convert(conn,new_name,&st);
2020                                 if (!new_name) {
2021                                         *perr = WERR_NOMEM;
2022                                         goto err_exit;
2023                                 }
2024                                 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
2025                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
2026                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
2027                                                         new_name, old_name));
2028                                         *perr = WERR_ACCESS_DENIED;
2029                                         ver = -1;
2030                                 }
2031                         }
2032                 }
2033         }
2034
2035         if (driver->dependentfiles) {
2036                 for (i=0; *driver->dependentfiles[i]; i++) {
2037                         if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
2038                                 !strequal(driver->dependentfiles[i], driver->datafile) &&
2039                                 !strequal(driver->dependentfiles[i], driver->configfile) &&
2040                                 !strequal(driver->dependentfiles[i], driver->helpfile)) {
2041                                 int j;
2042                                 for (j=0; j < i; j++) {
2043                                         if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
2044                                                 goto NextDriver;
2045                                         }
2046                                 }
2047
2048                                 new_name = talloc_asprintf(ctx,
2049                                                 "%s/%s",
2050                                                 architecture,
2051                                                 driver->dependentfiles[i]);
2052                                 if (!new_name) {
2053                                         *perr = WERR_NOMEM;
2054                                         goto err_exit;
2055                                 }
2056                                 old_name = talloc_asprintf(ctx,
2057                                                 "%s/%s",
2058                                                 new_dir,
2059                                                 driver->dependentfiles[i]);
2060                                 if (!old_name) {
2061                                         *perr = WERR_NOMEM;
2062                                         goto err_exit;
2063                                 }
2064                                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
2065                                         new_name = driver_unix_convert(conn,new_name,&st);
2066                                         if (!new_name) {
2067                                                 *perr = WERR_NOMEM;
2068                                                 goto err_exit;
2069                                         }
2070                                         if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name,
2071                                                         OPENX_FILE_EXISTS_TRUNCATE|
2072                                                         OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
2073                                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
2074                                                                 new_name, old_name));
2075                                                 *perr = WERR_ACCESS_DENIED;
2076                                                 ver = -1;
2077                                         }
2078                                 }
2079                         }
2080                 NextDriver: ;
2081                 }
2082         }
2083
2084   err_exit:
2085
2086         close_cnum(conn, user->vuid);
2087         unbecome_user();
2088
2089         if (W_ERROR_EQUAL(*perr, WERR_OK)) {
2090                 return WERR_OK;
2091         }
2092         if (ver == -1) {
2093                 return WERR_UNKNOWN_PRINTER_DRIVER;
2094         }
2095         return (*perr);
2096 }
2097
2098 /****************************************************************************
2099 ****************************************************************************/
2100
2101 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
2102 {
2103         TALLOC_CTX *ctx = talloc_tos();
2104         int len, buflen;
2105         const char *architecture;
2106         char *directory = NULL;
2107         fstring temp_name;
2108         char *key = NULL;
2109         uint8 *buf;
2110         int i, ret;
2111         TDB_DATA dbuf;
2112
2113         architecture = get_short_archi(driver->environment);
2114         if (!architecture) {
2115                 return (uint32)-1;
2116         }
2117
2118         /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2119          * \\server is added in the rpc server layer.
2120          * It does make sense to NOT store the server's name in the printer TDB.
2121          */
2122
2123         directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
2124                         architecture, driver->cversion);
2125         if (!directory) {
2126                 return (uint32)-1;
2127         }
2128
2129         /* .inf files do not always list a file for each of the four standard files. 
2130          * Don't prepend a path to a null filename, or client claims:
2131          *   "The server on which the printer resides does not have a suitable 
2132          *   <printer driver name> printer driver installed. Click OK if you 
2133          *   wish to install the driver on your local machine."
2134          */
2135         if (strlen(driver->driverpath)) {
2136                 fstrcpy(temp_name, driver->driverpath);
2137                 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
2138         }
2139
2140         if (strlen(driver->datafile)) {
2141                 fstrcpy(temp_name, driver->datafile);
2142                 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
2143         }
2144
2145         if (strlen(driver->configfile)) {
2146                 fstrcpy(temp_name, driver->configfile);
2147                 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
2148         }
2149
2150         if (strlen(driver->helpfile)) {
2151                 fstrcpy(temp_name, driver->helpfile);
2152                 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
2153         }
2154
2155         if (driver->dependentfiles) {
2156                 for (i=0; *driver->dependentfiles[i]; i++) {
2157                         fstrcpy(temp_name, driver->dependentfiles[i]);
2158                         slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
2159                 }
2160         }
2161
2162         key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
2163                         architecture, driver->cversion, driver->name);
2164         if (!key) {
2165                 return (uint32)-1;
2166         }
2167
2168         DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
2169
2170         buf = NULL;
2171         len = buflen = 0;
2172
2173  again:
2174         len = 0;
2175         len += tdb_pack(buf+len, buflen-len, "dffffffff",
2176                         driver->cversion,
2177                         driver->name,
2178                         driver->environment,
2179                         driver->driverpath,
2180                         driver->datafile,
2181                         driver->configfile,
2182                         driver->helpfile,
2183                         driver->monitorname,
2184                         driver->defaultdatatype);
2185
2186         if (driver->dependentfiles) {
2187                 for (i=0; *driver->dependentfiles[i]; i++) {
2188                         len += tdb_pack(buf+len, buflen-len, "f",
2189                                         driver->dependentfiles[i]);
2190                 }
2191         }
2192
2193         if (len != buflen) {
2194                 buf = (uint8 *)SMB_REALLOC(buf, len);
2195                 if (!buf) {
2196                         DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2197                         ret = -1;
2198                         goto done;
2199                 }
2200                 buflen = len;
2201                 goto again;
2202         }
2203
2204         dbuf.dptr = buf;
2205         dbuf.dsize = len;
2206
2207         ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2208
2209 done:
2210         if (ret)
2211                 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2212
2213         SAFE_FREE(buf);
2214         return ret;
2215 }
2216
2217 /****************************************************************************
2218 ****************************************************************************/
2219 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2220 {
2221         NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2222
2223         ZERO_STRUCT(info3);
2224         info3.cversion = driver->version;
2225         fstrcpy(info3.name,driver->name);
2226         fstrcpy(info3.environment,driver->environment);
2227         fstrcpy(info3.driverpath,driver->driverpath);
2228         fstrcpy(info3.datafile,driver->datafile);
2229         fstrcpy(info3.configfile,driver->configfile);
2230         fstrcpy(info3.helpfile,driver->helpfile);
2231         fstrcpy(info3.monitorname,driver->monitorname);
2232         fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2233         info3.dependentfiles = driver->dependentfiles;
2234
2235         return add_a_printer_driver_3(&info3);
2236 }
2237
2238
2239 /****************************************************************************
2240 ****************************************************************************/
2241 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2242 {
2243         NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2244
2245         ZERO_STRUCT(info);
2246
2247         fstrcpy(info.name, driver);
2248         fstrcpy(info.defaultdatatype, "RAW");
2249         
2250         fstrcpy(info.driverpath, "");
2251         fstrcpy(info.datafile, "");
2252         fstrcpy(info.configfile, "");
2253         fstrcpy(info.helpfile, "");
2254
2255         if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2256                 return WERR_NOMEM;
2257
2258         memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2259         fstrcpy(info.dependentfiles[0], "");
2260
2261         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
2262         if (!*info_ptr) {
2263                 SAFE_FREE(info.dependentfiles);
2264                 return WERR_NOMEM;
2265         }
2266         
2267         return WERR_OK;
2268 }
2269
2270 /****************************************************************************
2271 ****************************************************************************/
2272 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
2273 {
2274         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2275         TDB_DATA dbuf;
2276         const char *architecture;
2277         int len = 0;
2278         int i;
2279         char *key = NULL;
2280
2281         ZERO_STRUCT(driver);
2282
2283         architecture = get_short_archi(arch);
2284         if ( !architecture ) {
2285                 return WERR_UNKNOWN_PRINTER_DRIVER;
2286         }
2287
2288         /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2289
2290         if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2291                 version = 0;
2292
2293         DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2294
2295         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
2296                                 architecture, version, drivername) < 0) {
2297                 return WERR_NOMEM;
2298         }
2299
2300         dbuf = tdb_fetch_bystring(tdb_drivers, key);
2301         if (!dbuf.dptr) {
2302                 SAFE_FREE(key);
2303                 return WERR_UNKNOWN_PRINTER_DRIVER;
2304         }
2305
2306         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2307                           &driver.cversion,
2308                           driver.name,
2309                           driver.environment,
2310                           driver.driverpath,
2311                           driver.datafile,
2312                           driver.configfile,
2313                           driver.helpfile,
2314                           driver.monitorname,
2315                           driver.defaultdatatype);
2316
2317         i=0;
2318         while (len < dbuf.dsize) {
2319                 driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2320                 if ( !driver.dependentfiles ) {
2321                         DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2322                         break;
2323                 }
2324
2325                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2326                                   &driver.dependentfiles[i]);
2327                 i++;
2328         }
2329
2330         if ( driver.dependentfiles )
2331                 fstrcpy( driver.dependentfiles[i], "" );
2332
2333         SAFE_FREE(dbuf.dptr);
2334         SAFE_FREE(key);
2335
2336         if (len != dbuf.dsize) {
2337                 SAFE_FREE(driver.dependentfiles);
2338
2339                 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2340         }
2341
2342         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2343         if (!*info_ptr) {
2344                 SAFE_FREE(driver.dependentfiles);
2345                 return WERR_NOMEM;
2346         }
2347
2348         return WERR_OK;
2349 }
2350
2351 /****************************************************************************
2352  Debugging function, dump at level 6 the struct in the logs.
2353 ****************************************************************************/
2354
2355 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2356 {
2357         uint32 result;
2358         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2359         int i;
2360         
2361         DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2362         
2363         switch (level)
2364         {
2365                 case 3:
2366                 {
2367                         if (driver.info_3 == NULL)
2368                                 result=5;
2369                         else {
2370                                 info3=driver.info_3;
2371                         
2372                                 DEBUGADD(20,("version:[%d]\n",         info3->cversion));
2373                                 DEBUGADD(20,("name:[%s]\n",            info3->name));
2374                                 DEBUGADD(20,("environment:[%s]\n",     info3->environment));
2375                                 DEBUGADD(20,("driverpath:[%s]\n",      info3->driverpath));
2376                                 DEBUGADD(20,("datafile:[%s]\n",        info3->datafile));
2377                                 DEBUGADD(20,("configfile:[%s]\n",      info3->configfile));
2378                                 DEBUGADD(20,("helpfile:[%s]\n",        info3->helpfile));
2379                                 DEBUGADD(20,("monitorname:[%s]\n",     info3->monitorname));
2380                                 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2381                                 
2382                                 for (i=0; info3->dependentfiles &&
2383                                           *info3->dependentfiles[i]; i++) {
2384                                         DEBUGADD(20,("dependentfile:[%s]\n",
2385                                                       info3->dependentfiles[i]));
2386                                 }
2387                                 result=0;
2388                         }
2389                         break;
2390                 }
2391                 default:
2392                         DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2393                         result=1;
2394                         break;
2395         }
2396         
2397         return result;
2398 }
2399
2400 /****************************************************************************
2401 ****************************************************************************/
2402 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2403 {
2404         int len = 0;
2405
2406         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2407
2408         if (!nt_devmode)
2409                 return len;
2410
2411         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2412                         nt_devmode->devicename,
2413                         nt_devmode->formname,
2414
2415                         nt_devmode->specversion,
2416                         nt_devmode->driverversion,
2417                         nt_devmode->size,
2418                         nt_devmode->driverextra,
2419                         nt_devmode->orientation,
2420                         nt_devmode->papersize,
2421                         nt_devmode->paperlength,
2422                         nt_devmode->paperwidth,
2423                         nt_devmode->scale,
2424                         nt_devmode->copies,
2425                         nt_devmode->defaultsource,
2426                         nt_devmode->printquality,
2427                         nt_devmode->color,
2428                         nt_devmode->duplex,
2429                         nt_devmode->yresolution,
2430                         nt_devmode->ttoption,
2431                         nt_devmode->collate,
2432                         nt_devmode->logpixels,
2433                         
2434                         nt_devmode->fields,
2435                         nt_devmode->bitsperpel,
2436                         nt_devmode->pelswidth,
2437                         nt_devmode->pelsheight,
2438                         nt_devmode->displayflags,
2439                         nt_devmode->displayfrequency,
2440                         nt_devmode->icmmethod,
2441                         nt_devmode->icmintent,
2442                         nt_devmode->mediatype,
2443                         nt_devmode->dithertype,
2444                         nt_devmode->reserved1,
2445                         nt_devmode->reserved2,
2446                         nt_devmode->panningwidth,
2447                         nt_devmode->panningheight,
2448                         nt_devmode->nt_dev_private);
2449
2450         if (nt_devmode->nt_dev_private) {
2451                 len += tdb_pack(buf+len, buflen-len, "B",
2452                                 nt_devmode->driverextra,
2453                                 nt_devmode->nt_dev_private);
2454         }
2455
2456         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2457
2458         return len;
2459 }
2460
2461 /****************************************************************************
2462  Pack all values in all printer keys
2463  ***************************************************************************/
2464
2465 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2466 {
2467         int             len = 0;
2468         int             i, j;
2469         REGISTRY_VALUE  *val;
2470         REGVAL_CTR      *val_ctr;
2471         char *path = NULL;
2472         int             num_values;
2473
2474         if ( !data )
2475                 return 0;
2476
2477         /* loop over all keys */
2478
2479         for ( i=0; i<data->num_keys; i++ ) {
2480                 val_ctr = data->keys[i].values;
2481                 num_values = regval_ctr_numvals( val_ctr );
2482
2483                 /* pack the keyname followed by a empty value */
2484
2485                 len += tdb_pack(buf+len, buflen-len, "pPdB",
2486                                 &data->keys[i].name,
2487                                 data->keys[i].name,
2488                                 REG_NONE,
2489                                 0,
2490                                 NULL);
2491
2492                 /* now loop over all values */
2493
2494                 for ( j=0; j<num_values; j++ ) {
2495                         /* pathname should be stored as <key>\<value> */
2496
2497                         val = regval_ctr_specific_value( val_ctr, j );
2498                         if (asprintf(&path, "%s\\%s",
2499                                         data->keys[i].name,
2500                                         regval_name(val)) < 0) {
2501                                 return -1;
2502                         }
2503
2504                         len += tdb_pack(buf+len, buflen-len, "pPdB",
2505                                         val,
2506                                         path,
2507                                         regval_type(val),
2508                                         regval_size(val),
2509                                         regval_data_p(val) );
2510
2511                         DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2512                         SAFE_FREE(path);
2513                 }
2514
2515         }
2516
2517         /* terminator */
2518
2519         len += tdb_pack(buf+len, buflen-len, "p", NULL);
2520
2521         return len;
2522 }
2523
2524
2525 /****************************************************************************
2526  Delete a printer - this just deletes the printer info file, any open
2527  handles are not affected.
2528 ****************************************************************************/
2529
2530 uint32 del_a_printer(const char *sharename)
2531 {
2532         TDB_DATA kbuf;
2533         char *printdb_path = NULL;
2534         TALLOC_CTX *ctx = talloc_tos();
2535
2536         kbuf = make_printer_tdbkey(ctx, sharename);
2537         tdb_delete(tdb_printers, kbuf);
2538
2539         kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2540         tdb_delete(tdb_printers, kbuf);
2541
2542         close_all_print_db();
2543
2544         if (geteuid() == 0) {
2545                 if (asprintf(&printdb_path, "%s%s.tdb",
2546                                 lock_path("printing/"),
2547                                 sharename) < 0) {
2548                         return (uint32)-1;
2549                 }
2550                 unlink(printdb_path);
2551                 SAFE_FREE(printdb_path);
2552         }
2553
2554         return 0;
2555 }
2556
2557 /****************************************************************************
2558 ****************************************************************************/
2559 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2560 {
2561         uint8 *buf;
2562         int buflen, len;
2563         int retlen;
2564         WERROR ret;
2565         TDB_DATA kbuf, dbuf;
2566         
2567         /*
2568          * in addprinter: no servername and the printer is the name
2569          * in setprinter: servername is \\server
2570          *                and printer is \\server\\printer
2571          *
2572          * Samba manages only local printers.
2573          * we currently don't support things like i
2574          * path=\\other_server\printer
2575          *
2576          * We only store the printername, not \\server\printername
2577          */
2578
2579         if ( info->servername[0] != '\0' ) {
2580                 trim_string(info->printername, info->servername, NULL);
2581                 trim_char(info->printername, '\\', '\0');
2582                 info->servername[0]='\0';
2583         }
2584
2585         /*
2586          * JFM: one day I'll forget.
2587          * below that's info->portname because that's the SAMBA sharename
2588          * and I made NT 'thinks' it's the portname
2589          * the info->sharename is the thing you can name when you add a printer
2590          * that's the short-name when you create shared printer for 95/98
2591          * So I've made a limitation in SAMBA: you can only have 1 printer model
2592          * behind a SAMBA share.
2593          */
2594
2595         buf = NULL;
2596         buflen = 0;
2597
2598  again:
2599         len = 0;
2600         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2601                         info->attributes,
2602                         info->priority,
2603                         info->default_priority,
2604                         info->starttime,
2605                         info->untiltime,
2606                         info->status,
2607                         info->cjobs,
2608                         info->averageppm,
2609                         info->changeid,
2610                         info->c_setprinter,
2611                         info->setuptime,
2612                         info->servername,
2613                         info->printername,
2614                         info->sharename,
2615                         info->portname,
2616                         info->drivername,
2617                         info->comment,
2618                         info->location,
2619                         info->sepfile,
2620                         info->printprocessor,
2621                         info->datatype,
2622                         info->parameters);
2623
2624         len += pack_devicemode(info->devmode, buf+len, buflen-len);
2625         retlen = pack_values( info->data, buf+len, buflen-len );
2626         if (retlen == -1) {
2627                 ret = WERR_NOMEM;
2628                 goto done;
2629         }
2630         len += retlen;
2631
2632         if (buflen != len) {
2633                 buf = (uint8 *)SMB_REALLOC(buf, len);
2634                 if (!buf) {
2635                         DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2636                         ret = WERR_NOMEM;
2637                         goto done;
2638                 }
2639                 buflen = len;
2640                 goto again;
2641         }
2642
2643         kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2644
2645         dbuf.dptr = buf;
2646         dbuf.dsize = len;
2647
2648         ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2649
2650 done:
2651         if (!W_ERROR_IS_OK(ret))
2652                 DEBUG(8, ("error updating printer to tdb on disk\n"));
2653
2654         SAFE_FREE(buf);
2655
2656         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2657                  info->sharename, info->drivername, info->portname, len));
2658
2659         return ret;
2660 }
2661
2662
2663 /****************************************************************************
2664  Malloc and return an NT devicemode.
2665 ****************************************************************************/
2666
2667 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2668 {
2669
2670         char adevice[MAXDEVICENAME];
2671         NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2672
2673         if (nt_devmode == NULL) {
2674                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2675                 return NULL;
2676         }
2677
2678         ZERO_STRUCTP(nt_devmode);
2679
2680         slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2681         fstrcpy(nt_devmode->devicename, adevice);       
2682         
2683         fstrcpy(nt_devmode->formname, "Letter");
2684
2685         nt_devmode->specversion      = 0x0401;
2686         nt_devmode->driverversion    = 0x0400;
2687         nt_devmode->size             = 0x00DC;
2688         nt_devmode->driverextra      = 0x0000;
2689         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY |
2690                                        DEFAULTSOURCE | COPIES | SCALE |
2691                                        PAPERSIZE | ORIENTATION;
2692         nt_devmode->orientation      = 1;
2693         nt_devmode->papersize        = PAPER_LETTER;
2694         nt_devmode->paperlength      = 0;
2695         nt_devmode->paperwidth       = 0;
2696         nt_devmode->scale            = 0x64;
2697         nt_devmode->copies           = 1;
2698         nt_devmode->defaultsource    = BIN_FORMSOURCE;
2699         nt_devmode->printquality     = RES_HIGH;           /* 0x0258 */
2700         nt_devmode->color            = COLOR_MONOCHROME;
2701         nt_devmode->duplex           = DUP_SIMPLEX;
2702         nt_devmode->yresolution      = 0;
2703         nt_devmode->ttoption         = TT_SUBDEV;
2704         nt_devmode->collate          = COLLATE_FALSE;
2705         nt_devmode->icmmethod        = 0;
2706         nt_devmode->icmintent        = 0;
2707         nt_devmode->mediatype        = 0;
2708         nt_devmode->dithertype       = 0;
2709
2710         /* non utilisés par un driver d'imprimante */
2711         nt_devmode->logpixels        = 0;
2712         nt_devmode->bitsperpel       = 0;
2713         nt_devmode->pelswidth        = 0;
2714         nt_devmode->pelsheight       = 0;
2715         nt_devmode->displayflags     = 0;
2716         nt_devmode->displayfrequency = 0;
2717         nt_devmode->reserved1        = 0;
2718         nt_devmode->reserved2        = 0;
2719         nt_devmode->panningwidth     = 0;
2720         nt_devmode->panningheight    = 0;
2721         
2722         nt_devmode->nt_dev_private = NULL;
2723         return nt_devmode;
2724 }
2725
2726 /****************************************************************************
2727  Deepcopy an NT devicemode.
2728 ****************************************************************************/
2729
2730 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2731 {
2732         NT_DEVICEMODE *new_nt_devicemode = NULL;
2733
2734         if ( !nt_devicemode )
2735                 return NULL;
2736
2737         if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2738                 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2739                 return NULL;
2740         }
2741
2742         new_nt_devicemode->nt_dev_private = NULL;
2743         if (nt_devicemode->nt_dev_private != NULL) {
2744                 if ((new_nt_devicemode->nt_dev_private = (uint8 *)memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2745                         SAFE_FREE(new_nt_devicemode);
2746                         DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2747                         return NULL;
2748         }
2749         }
2750
2751         return new_nt_devicemode;
2752 }
2753
2754 /****************************************************************************
2755  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2756 ****************************************************************************/
2757
2758 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2759 {
2760         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2761
2762         if(nt_devmode == NULL)
2763                 return;
2764
2765         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2766
2767         SAFE_FREE(nt_devmode->nt_dev_private);
2768         SAFE_FREE(*devmode_ptr);
2769 }
2770
2771 /****************************************************************************
2772  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2773 ****************************************************************************/
2774
2775 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2776 {
2777         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2778
2779         if ( !info )
2780                 return;
2781
2782         free_nt_devicemode(&info->devmode);
2783
2784         TALLOC_FREE( *info_ptr );
2785 }
2786
2787
2788 /****************************************************************************
2789 ****************************************************************************/
2790 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2791 {
2792         int len = 0;
2793         int extra_len = 0;
2794         NT_DEVICEMODE devmode;
2795         
2796         ZERO_STRUCT(devmode);
2797
2798         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2799
2800         if (!*nt_devmode) return len;
2801
2802         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2803                           devmode.devicename,
2804                           devmode.formname,
2805
2806                           &devmode.specversion,
2807                           &devmode.driverversion,
2808                           &devmode.size,
2809                           &devmode.driverextra,
2810                           &devmode.orientation,
2811                           &devmode.papersize,
2812                           &devmode.paperlength,
2813                           &devmode.paperwidth,
2814                           &devmode.scale,
2815                           &devmode.copies,
2816                           &devmode.defaultsource,
2817                           &devmode.printquality,
2818                           &devmode.color,
2819                           &devmode.duplex,
2820                           &devmode.yresolution,
2821                           &devmode.ttoption,
2822                           &devmode.collate,
2823                           &devmode.logpixels,
2824                         
2825                           &devmode.fields,
2826                           &devmode.bitsperpel,
2827                           &devmode.pelswidth,
2828                           &devmode.pelsheight,
2829                           &devmode.displayflags,
2830                           &devmode.displayfrequency,
2831                           &devmode.icmmethod,
2832                           &devmode.icmintent,
2833                           &devmode.mediatype,
2834                           &devmode.dithertype,
2835                           &devmode.reserved1,
2836                           &devmode.reserved2,
2837                           &devmode.panningwidth,
2838                           &devmode.panningheight,
2839                           &devmode.nt_dev_private);
2840         
2841         if (devmode.nt_dev_private) {
2842                 /* the len in tdb_unpack is an int value and
2843                  * devmode.driverextra is only a short
2844                  */
2845                 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2846                 devmode.driverextra=(uint16)extra_len;
2847                 
2848                 /* check to catch an invalid TDB entry so we don't segfault */
2849                 if (devmode.driverextra == 0) {
2850                         devmode.nt_dev_private = NULL;
2851                 }
2852         }
2853
2854         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2855         if (!*nt_devmode) {
2856                 SAFE_FREE(devmode.nt_dev_private);
2857                 return -1;
2858         }
2859
2860         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2861         if (devmode.nt_dev_private)
2862                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2863
2864         return len;
2865 }
2866
2867 /****************************************************************************
2868  Allocate and initialize a new slot.
2869 ***************************************************************************/
2870  
2871 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2872 {
2873         NT_PRINTER_KEY  *d;
2874         int             key_index;
2875         
2876         if ( !name || !data )
2877                 return -1;
2878
2879         /* allocate another slot in the NT_PRINTER_KEY array */
2880         
2881         if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2882                 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2883                 return -1;
2884         }
2885
2886         data->keys = d;
2887         
2888         key_index = data->num_keys;
2889         
2890         /* initialze new key */
2891         
2892         data->keys[key_index].name = talloc_strdup( data, name );
2893         
2894         if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) ) 
2895                 return -1;
2896         
2897         data->num_keys++;
2898
2899         DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2900         
2901         return key_index;
2902 }
2903
2904 /****************************************************************************
2905  search for a registry key name in the existing printer data
2906  ***************************************************************************/
2907
2908 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2909 {
2910         int i;
2911         
2912         for ( i=0; i<data->num_keys; i++ ) {
2913                 if ( strequal( data->keys[i].name, name ) ) {
2914                 
2915                         /* cleanup memory */
2916                         
2917                         TALLOC_FREE( data->keys[i].name );
2918                         TALLOC_FREE( data->keys[i].values );
2919                         
2920                         /* if not the end of the array, move remaining elements down one slot */
2921                         
2922                         data->num_keys--;
2923                         if ( data->num_keys && (i < data->num_keys) )
2924                                 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2925                                 
2926                         break;
2927                 }
2928         }
2929         
2930
2931         return data->num_keys;
2932 }
2933
2934 /****************************************************************************
2935  search for a registry key name in the existing printer data
2936  ***************************************************************************/
2937  
2938 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2939 {
2940         int             key_index = -1;
2941         int             i;
2942         
2943         if ( !data || !name )
2944                 return -1;
2945
2946         DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2947
2948         /* loop over all existing keys */
2949         
2950         for ( i=0; i<data->num_keys; i++ ) {
2951                 if ( strequal(data->keys[i].name, name) ) {
2952                         DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2953                         key_index = i;
2954                         break;
2955                 
2956                 }
2957         }
2958         
2959         return key_index;
2960 }
2961
2962 /****************************************************************************
2963  ***************************************************************************/
2964
2965 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2966 {
2967         int     i, j;
2968         int     key_len;
2969         int     num_subkeys = 0;
2970         char    *p;
2971         fstring *subkeys_ptr = NULL;
2972         fstring subkeyname;
2973         
2974         *subkeys = NULL;
2975
2976         if ( !data )
2977                 return 0;
2978
2979         if ( !key )
2980                 return -1;
2981
2982         /* special case of asking for the top level printer data registry key names */
2983
2984         if ( strlen(key) == 0 ) {
2985                 for ( i=0; i<data->num_keys; i++ ) {
2986                 
2987                         /* found a match, so allocate space and copy the name */
2988                         
2989                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2990                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 
2991                                         num_subkeys+1));
2992                                 return -1;
2993                         }
2994                         
2995                         fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2996                         num_subkeys++;
2997                 }
2998
2999                 goto done;
3000         }
3001                 
3002         /* asking for the subkeys of some key */
3003         /* subkey paths are stored in the key name using '\' as the delimiter */
3004
3005         for ( i=0; i<data->num_keys; i++ ) {
3006                 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
3007                         
3008                         /* if we found the exact key, then break */
3009                         key_len = strlen( key );
3010                         if ( strlen(data->keys[i].name) == key_len )
3011                                 break;
3012                         
3013                         /* get subkey path */
3014
3015                         p = data->keys[i].name + key_len;
3016                         if ( *p == '\\' )
3017                                 p++;
3018                         fstrcpy( subkeyname, p );
3019                         if ( (p = strchr( subkeyname, '\\' )) )
3020                                 *p = '\0';
3021                         
3022                         /* don't add a key more than once */
3023                         
3024                         for ( j=0; j<num_subkeys; j++ ) {
3025                                 if ( strequal( subkeys_ptr[j], subkeyname ) )
3026                                         break;
3027                         }
3028                         
3029                         if ( j != num_subkeys )
3030                                 continue;
3031
3032                         /* found a match, so allocate space and copy the name */
3033                         
3034                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3035                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 
3036                                         num_subkeys+1));
3037                                 return 0;
3038                         }
3039                         
3040                         fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
3041                         num_subkeys++;
3042                 }
3043                 
3044         }
3045         
3046         /* return error if the key was not found */
3047         
3048         if ( i == data->num_keys ) {
3049                 SAFE_FREE(subkeys_ptr);
3050                 return -1;
3051         }
3052         
3053 done:
3054         /* tag off the end */
3055         
3056         if (num_subkeys)
3057                 fstrcpy(subkeys_ptr[num_subkeys], "" );
3058         
3059         *subkeys = subkeys_ptr;
3060
3061         return num_subkeys;
3062 }
3063
3064 #ifdef HAVE_ADS
3065 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name, 
3066                             const char *sz)
3067 {
3068         smb_ucs2_t conv_str[1024];
3069         size_t str_size;
3070
3071         regval_ctr_delvalue(ctr, val_name);
3072         str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
3073                              STR_TERMINATE | STR_NOALIGN);
3074         regval_ctr_addvalue(ctr, val_name, REG_SZ, 
3075                             (char *) conv_str, str_size);
3076 }
3077
3078 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name, 
3079                                uint32 dword)
3080 {
3081         regval_ctr_delvalue(ctr, val_name);
3082         regval_ctr_addvalue(ctr, val_name, REG_DWORD,
3083                             (char *) &dword, sizeof(dword));
3084 }
3085
3086 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
3087                               bool b)
3088 {
3089         uint8 bin_bool = (b ? 1 : 0);
3090         regval_ctr_delvalue(ctr, val_name);
3091         regval_ctr_addvalue(ctr, val_name, REG_BINARY, 
3092                             (char *) &bin_bool, sizeof(bin_bool));
3093 }
3094
3095 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
3096                                          const char *multi_sz)
3097 {
3098         smb_ucs2_t *conv_strs = NULL;
3099         size_t str_size;
3100
3101         /* a multi-sz has to have a null string terminator, i.e., the last
3102            string must be followed by two nulls */
3103         str_size = strlen(multi_sz) + 2;
3104         conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
3105         if (!conv_strs) {
3106                 return;
3107         }
3108
3109         /* Change to byte units. */
3110         str_size *= sizeof(smb_ucs2_t);
3111         push_ucs2(NULL, conv_strs, multi_sz, str_size, 
3112                   STR_TERMINATE | STR_NOALIGN);
3113
3114         regval_ctr_delvalue(ctr, val_name);
3115         regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ, 
3116                             (char *) conv_strs, str_size);      
3117         safe_free(conv_strs);
3118         
3119 }
3120
3121 /****************************************************************************
3122  * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3123  *
3124  * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3125  * @return bool indicating success or failure
3126  ***************************************************************************/
3127
3128 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
3129 {
3130         REGVAL_CTR *ctr = NULL;
3131         fstring longname;
3132         const char *dnssuffix;
3133         char *allocated_string = NULL;
3134         const char *ascii_str;
3135         int i;
3136
3137         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3138                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3139         ctr = info2->data->keys[i].values;
3140
3141         map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3142         map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3143
3144         /* we make the assumption that the netbios name is the same
3145            as the DNS name sinc ethe former will be what we used to
3146            join the domain */
3147
3148         dnssuffix = get_mydnsdomname(talloc_tos());
3149         if (dnssuffix && *dnssuffix) {
3150                 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3151         } else {
3152                 fstrcpy( longname, global_myname() );
3153         }
3154
3155         map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3156
3157         asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
3158         map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3159         SAFE_FREE(allocated_string);
3160
3161         map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3162         map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3163         map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3164         map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3165         map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3166         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3167         map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3168         map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3169         map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3170
3171         map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3172                           (info2->attributes & 
3173                            PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3174
3175         switch (info2->attributes & 0x3) {