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