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