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