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