r10154: Fix crash bug on security descriptor upgrade (as seen on x86_64).
[metze/samba/wip.git] / source3 / printing / nt_printing.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2000.
6  *  Copyright (C) Gerald Carter                2002-2005.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 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, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include "includes.h"
24
25 extern struct current_user current_user;
26
27 static TDB_CONTEXT *tdb_forms; /* used for forms files */
28 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29 static TDB_CONTEXT *tdb_printers; /* used for printers files */
30
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
37  
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
41 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
42 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
43
44 /* Map generic permissions to printer object specific permissions */
45
46 GENERIC_MAPPING printer_generic_mapping = {
47         PRINTER_READ,
48         PRINTER_WRITE,
49         PRINTER_EXECUTE,
50         PRINTER_ALL_ACCESS
51 };
52
53 STANDARD_MAPPING printer_std_mapping = {
54         PRINTER_READ,
55         PRINTER_WRITE,
56         PRINTER_EXECUTE,
57         PRINTER_ALL_ACCESS
58 };
59
60 /* Map generic permissions to print server object specific permissions */
61
62 GENERIC_MAPPING printserver_generic_mapping = {
63         SERVER_READ,
64         SERVER_WRITE,
65         SERVER_EXECUTE,
66         SERVER_ALL_ACCESS
67 };
68
69 STANDARD_MAPPING printserver_std_mapping = {
70         SERVER_READ,
71         SERVER_WRITE,
72         SERVER_EXECUTE,
73         SERVER_ALL_ACCESS
74 };
75
76 /* We need one default form to support our default printer. Msoft adds the
77 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
78 array index). Letter is always first, so (for the current code) additions
79 always put things in the correct order. */
80 static const nt_forms_struct default_forms[] = {
81         {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82         {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83         {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
84         {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
85         {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
86         {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
87         {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
88         {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
89         {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90         {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91         {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
92         {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
93         {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
94         {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
95         {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
96         {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
97         {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
98         {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
99         {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
100         {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
101         {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
102         {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
103         {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
104         {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
105         {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
106         {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
107         {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
108         {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
109         {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
110         {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
111         {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
112         {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
113         {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
114         {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
115         {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
116         {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
117         {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
118         {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
119         {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
120         {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
121         {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
122         {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
123         {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
124         {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
125         {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
126         {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
127         {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
128         {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129         {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130         {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
131         {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
132         {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
133         {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
134         {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
135         {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
136         {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137         {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
138         {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
139         {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
140         {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
141         {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
142         {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
143         {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
144         {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
145         {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
146         {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
147         {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
148         {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
149         {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
150         {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
151         {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
152         {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
153         {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
154         {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
155         {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
156         {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
157         {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
158         {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
159         {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
160         {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
161         {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
162         {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
163         {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
164         {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
165         {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
166         {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
167         {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
168         {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
169         {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
170         {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
171         {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
172         {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
173         {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
174         {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
175         {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
176         {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
177         {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
178         {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
179         {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
180         {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
181         {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
182         {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
183         {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
184         {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
185         {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
186         {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
187         {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
188         {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
189         {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
190         {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
191         {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
192         {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
193         {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
194         {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
195         {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
196         {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
197         {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
198         {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
199 };
200
201 struct table_node {
202         const char      *long_archi;
203         const char      *short_archi;
204         int     version;
205 };
206  
207 #define SPL_ARCH_WIN40          "WIN40"
208 #define SPL_ARCH_W32X86         "W32X86"
209 #define SPL_ARCH_W32MIPS        "W32MIPS"
210 #define SPL_ARCH_W32ALPHA       "W32ALPHA"
211 #define SPL_ARCH_W32PPC         "W32PPC"
212 #define SPL_ARCH_IA64           "IA64"
213 #define SPL_ARCH_X64            "x64"
214
215 static const struct table_node archi_table[]= {
216
217         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
218         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
219         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
220         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
221         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
222         {"Windows IA64",         SPL_ARCH_IA64,         3 },
223         {"Windows x64",          SPL_ARCH_X64,          3 },
224         {NULL,                   "",            -1 }
225 };
226
227
228 /****************************************************************************
229  generate a new TDB_DATA key for storing a printer
230 ****************************************************************************/
231
232 static TDB_DATA make_printer_tdbkey( const char *sharename )
233 {
234         fstring share;
235         static pstring keystr;
236         TDB_DATA key;
237         
238         fstrcpy( share, sharename );
239         strlower_m( share );
240         
241         pstr_sprintf( keystr, "%s%s", PRINTERS_PREFIX, share );
242         
243         key.dptr = keystr;
244         key.dsize = strlen(keystr)+1;
245
246         return key;
247 }
248
249 /****************************************************************************
250  generate a new TDB_DATA key for storing a printer security descriptor
251 ****************************************************************************/
252
253 static char* make_printers_secdesc_tdbkey( const char* sharename  )
254 {
255         fstring share;
256         static pstring keystr;
257         
258         fstrcpy( share, sharename );
259         strlower_m( share );
260         
261         pstr_sprintf( keystr, "%s%s", SECDESC_PREFIX, share );
262
263         return keystr;
264 }
265
266 /****************************************************************************
267 ****************************************************************************/
268
269 static BOOL upgrade_to_version_3(void)
270 {
271         TDB_DATA kbuf, newkey, dbuf;
272  
273         DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
274  
275         for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
276                         newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
277
278                 dbuf = tdb_fetch(tdb_drivers, kbuf);
279
280                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
281                         DEBUG(0,("upgrade_to_version_3:moving form\n"));
282                         if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
283                                 SAFE_FREE(dbuf.dptr);
284                                 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
285                                 return False;
286                         }
287                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
288                                 SAFE_FREE(dbuf.dptr);
289                                 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
290                                 return False;
291                         }
292                 }
293  
294                 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
295                         DEBUG(0,("upgrade_to_version_3:moving printer\n"));
296                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
297                                 SAFE_FREE(dbuf.dptr);
298                                 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
299                                 return False;
300                         }
301                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
302                                 SAFE_FREE(dbuf.dptr);
303                                 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
304                                 return False;
305                         }
306                 }
307  
308                 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
309                         DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
310                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
311                                 SAFE_FREE(dbuf.dptr);
312                                 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
313                                 return False;
314                         }
315                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
316                                 SAFE_FREE(dbuf.dptr);
317                                 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
318                                 return False;
319                         }
320                 }
321  
322                 SAFE_FREE(dbuf.dptr);
323         }
324
325         return True;
326 }
327
328 /*******************************************************************
329  Fix an issue with security descriptors.  Printer sec_desc must 
330  use more than the generic bits that were previously used 
331  in <= 3.0.14a.  They must also have a owner and group SID assigned.
332  Otherwise, any printers than have been migrated to a Windows 
333  host using printmig.exe will not be accessible.
334 *******************************************************************/
335
336 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
337                             TDB_DATA data, void *state )
338 {
339         prs_struct ps;
340         SEC_DESC_BUF *sd_orig = NULL;
341         SEC_DESC_BUF *sd_new, *sd_store;
342         SEC_DESC *sec, *new_sec;
343         TALLOC_CTX *ctx = state;
344         int result, i;
345         uint32 sd_size;
346         size_t size_new_sec;
347         DOM_SID sid;
348
349         if (!data.dptr || data.dsize == 0)
350                 return 0;
351
352         if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 )
353                 return 0;
354
355         /* upgrade the security descriptor */
356
357         ZERO_STRUCT( ps );
358
359         prs_init( &ps, 0, ctx, UNMARSHALL );
360         prs_give_memory( &ps, data.dptr, data.dsize, True );
361
362         if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
363                 /* delete bad entries */
364                 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si.  Deleting....\n", key.dptr ));
365                 tdb_delete( tdb_printers, key );
366                 return 0;
367         }
368
369         sec = sd_orig->sec;
370                 
371         /* is this even valid? */
372         
373         if ( !sec->dacl )
374                 return 0;
375                 
376         /* update access masks */
377         
378         for ( i=0; i<sec->dacl->num_aces; i++ ) {
379                 switch ( sec->dacl->ace[i].info.mask ) {
380                         case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
381                                 sec->dacl->ace[i].info.mask = PRINTER_ACE_PRINT;
382                                 break;
383                                 
384                         case GENERIC_ALL_ACCESS:
385                                 sec->dacl->ace[i].info.mask = PRINTER_ACE_FULL_CONTROL;
386                                 break;
387                                 
388                         case READ_CONTROL_ACCESS:
389                                 sec->dacl->ace[i].info.mask = PRINTER_ACE_MANAGE_DOCUMENTS;
390                         
391                         default:        /* no change */
392                                 break;
393                 }
394         }
395
396         /* create a new SEC_DESC with the appropriate owner and group SIDs */
397
398         string_to_sid(&sid, "S-1-5-32-544" );
399         new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
400                 &sid, &sid,
401                 NULL, NULL, &size_new_sec );
402         sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
403
404         if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
405                 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
406                 return 0;
407         }
408         
409         /* store it back */
410         
411         sd_size = sec_desc_size(sd_store->sec) + sizeof(SEC_DESC_BUF);
412         prs_init(&ps, sd_size, ctx, MARSHALL);
413
414         if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
415                 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
416                 return 0;
417         }
418
419         data.dptr = prs_data_p( &ps );
420         data.dsize = sd_size;
421         
422         result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
423
424         prs_mem_free( &ps );
425         
426         /* 0 to continue and non-zero to stop traversal */
427
428         return (result == -1);
429 }
430
431 /*******************************************************************
432 *******************************************************************/
433
434 static BOOL upgrade_to_version_4(void)
435 {
436         TALLOC_CTX *ctx;
437         int result;
438
439         DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
440
441         if ( !(ctx = talloc_init( "upgrade_to_version_4" )) ) 
442                 return False;
443
444         result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
445
446         talloc_destroy( ctx );
447
448         return ( result != -1 );
449 }
450
451 /*******************************************************************
452  Fix an issue with security descriptors.  Printer sec_desc must 
453  use more than the generic bits that were previously used 
454  in <= 3.0.14a.  They must also have a owner and group SID assigned.
455  Otherwise, any printers than have been migrated to a Windows 
456  host using printmig.exe will not be accessible.
457 *******************************************************************/
458
459 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
460                                   TDB_DATA data, void *state )
461 {
462         TDB_DATA new_key;
463         
464         if (!data.dptr || data.dsize == 0)
465                 return 0;
466
467         /* upgrade printer records and security descriptors */
468         
469         if ( strncmp( key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
470                 new_key = make_printer_tdbkey( key.dptr+strlen(PRINTERS_PREFIX) );
471         }
472         else if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
473                 new_key.dptr = make_printers_secdesc_tdbkey( key.dptr+strlen(SECDESC_PREFIX) );
474                 new_key.dsize = strlen( new_key.dptr ) + 1;
475         }
476         else {
477                 /* ignore this record */
478                 return 0;
479         }
480                 
481         /* delete the original record and store under the normalized key */
482         
483         if ( tdb_delete( the_tdb, key ) != 0 ) {
484                 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n", 
485                         key.dptr));
486                 return 1;
487         }
488         
489         if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
490                 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
491                         key.dptr));
492                 return 1;
493         }
494         
495         return 0;
496 }
497
498 /*******************************************************************
499 *******************************************************************/
500
501 static BOOL upgrade_to_version_5(void)
502 {
503         TALLOC_CTX *ctx;
504         int result;
505
506         DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
507
508         if ( !(ctx = talloc_init( "upgrade_to_version_5" )) ) 
509                 return False;
510
511         result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
512
513         talloc_destroy( ctx );
514
515         return ( result != -1 );
516 }
517
518 /****************************************************************************
519  Open the NT printing tdbs. Done once before fork().
520 ****************************************************************************/
521
522 BOOL nt_printing_init(void)
523 {
524         const char *vstring = "INFO/version";
525         WERROR win_rc;
526         int32 vers_id;
527
528         if ( tdb_drivers && tdb_printers && tdb_forms )
529                 return True;
530  
531         if (tdb_drivers)
532                 tdb_close(tdb_drivers);
533         tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
534         if (!tdb_drivers) {
535                 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
536                         lock_path("ntdrivers.tdb"), strerror(errno) ));
537                 return False;
538         }
539  
540         if (tdb_printers)
541                 tdb_close(tdb_printers);
542         tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
543         if (!tdb_printers) {
544                 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
545                         lock_path("ntprinters.tdb"), strerror(errno) ));
546                 return False;
547         }
548  
549         if (tdb_forms)
550                 tdb_close(tdb_forms);
551         tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
552         if (!tdb_forms) {
553                 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
554                         lock_path("ntforms.tdb"), strerror(errno) ));
555                 return False;
556         }
557  
558         /* handle a Samba upgrade */
559         
560         vers_id = tdb_fetch_int32(tdb_drivers, vstring);
561         if (vers_id == -1) {
562                 DEBUG(10, ("Fresh database\n"));
563                 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
564                 vers_id = NTDRIVERS_DATABASE_VERSION_5;
565         }
566
567         if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
568
569                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) { 
570                         if (!upgrade_to_version_3())
571                                 return False;
572                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
573                         vers_id = NTDRIVERS_DATABASE_VERSION_3;
574                 } 
575                 
576                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
577                         /* Written on a bigendian machine with old fetch_int code. Save as le. */
578                         /* The only upgrade between V2 and V3 is to save the version in little-endian. */
579                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
580                         vers_id = NTDRIVERS_DATABASE_VERSION_3;
581                 }
582
583                 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
584                         if ( !upgrade_to_version_4() )
585                                 return False;
586                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
587                         vers_id = NTDRIVERS_DATABASE_VERSION_4;
588                 }
589
590                 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
591                         if ( !upgrade_to_version_5() )
592                                 return False;
593                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
594                         vers_id = NTDRIVERS_DATABASE_VERSION_5;
595                 }
596
597
598                 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
599                         DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
600                         return False;
601                 }
602         }
603         
604         update_c_setprinter(True);
605
606         /*
607          * register callback to handle updating printers as new
608          * drivers are installed
609          */
610
611         message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
612
613         /*
614          * register callback to handle updating printer data
615          * when a driver is initialized
616          */
617
618         message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
619
620         /* of course, none of the message callbacks matter if you don't
621            tell messages.c that you interested in receiving PRINT_GENERAL 
622            msgs.  This is done in claim_connection() */
623
624
625         if ( lp_security() == SEC_ADS ) {
626                 win_rc = check_published_printers();
627                 if (!W_ERROR_IS_OK(win_rc))
628                         DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
629         }
630
631         return True;
632 }
633
634 /*******************************************************************
635  Function to allow filename parsing "the old way".
636 ********************************************************************/
637
638 static BOOL driver_unix_convert(char *name,connection_struct *conn,
639                 char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
640 {
641         unix_format(name);
642         unix_clean_name(name);
643         trim_string(name,"/","/");
644         return unix_convert(name, conn, saved_last_component, bad_path, pst);
645 }
646
647 /*******************************************************************
648  tdb traversal function for counting printers.
649 ********************************************************************/
650
651 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
652                                       TDB_DATA data, void *context)
653 {
654         int *printer_count = (int*)context;
655  
656         if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
657                 (*printer_count)++;
658                 DEBUG(10,("traverse_counting_printers: printer = [%s]  printer_count = %d\n", key.dptr, *printer_count));
659         }
660  
661         return 0;
662 }
663  
664 /*******************************************************************
665  Update the spooler global c_setprinter. This variable is initialized
666  when the parent smbd starts with the number of existing printers. It
667  is monotonically increased by the current number of printers *after*
668  each add or delete printer RPC. Only Microsoft knows why... JRR020119
669 ********************************************************************/
670
671 uint32 update_c_setprinter(BOOL initialize)
672 {
673         int32 c_setprinter;
674         int32 printer_count = 0;
675  
676         tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
677  
678         /* Traverse the tdb, counting the printers */
679         tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
680  
681         /* If initializing, set c_setprinter to current printers count
682          * otherwise, bump it by the current printer count
683          */
684         if (!initialize)
685                 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
686         else
687                 c_setprinter = printer_count;
688  
689         DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
690         tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
691  
692         tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
693  
694         return (uint32)c_setprinter;
695 }
696
697 /*******************************************************************
698  Get the spooler global c_setprinter, accounting for initialization.
699 ********************************************************************/
700
701 uint32 get_c_setprinter(void)
702 {
703         int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
704  
705         if (c_setprinter == (int32)-1)
706                 c_setprinter = update_c_setprinter(True);
707  
708         DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
709  
710         return (uint32)c_setprinter;
711 }
712
713 /****************************************************************************
714  Get builtin form struct list.
715 ****************************************************************************/
716
717 int get_builtin_ntforms(nt_forms_struct **list)
718 {
719         *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
720         return sizeof(default_forms) / sizeof(default_forms[0]);
721 }
722
723 /****************************************************************************
724  get a builtin form struct
725 ****************************************************************************/
726
727 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
728 {
729         int i,count;
730         fstring form_name;
731         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
732         DEBUGADD(6,("Looking for builtin form %s \n", form_name));
733         count = sizeof(default_forms) / sizeof(default_forms[0]);
734         for (i=0;i<count;i++) {
735                 if (strequal(form_name,default_forms[i].name)) {
736                         DEBUGADD(6,("Found builtin form %s \n", form_name));
737                         memcpy(form,&default_forms[i],sizeof(*form));
738                         break;
739                 }
740         }
741
742         return (i !=count);
743 }
744
745 /****************************************************************************
746 get a form struct list
747 ****************************************************************************/
748 int get_ntforms(nt_forms_struct **list)
749 {
750         TDB_DATA kbuf, newkey, dbuf;
751         nt_forms_struct *tl;
752         nt_forms_struct form;
753         int ret;
754         int i;
755         int n = 0;
756
757         for (kbuf = tdb_firstkey(tdb_forms);
758              kbuf.dptr;
759              newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) 
760         {
761                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) 
762                         continue;
763                 
764                 dbuf = tdb_fetch(tdb_forms, kbuf);
765                 if (!dbuf.dptr) 
766                         continue;
767
768                 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
769                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
770                                  &i, &form.flag, &form.width, &form.length, &form.left,
771                                  &form.top, &form.right, &form.bottom);
772                 SAFE_FREE(dbuf.dptr);
773                 if (ret != dbuf.dsize) 
774                         continue;
775
776                 tl = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
777                 if (!tl) {
778                         DEBUG(0,("get_ntforms: Realloc fail.\n"));
779                         return 0;
780                 }
781                 *list = tl;
782                 (*list)[n] = form;
783                 n++;
784         }
785         
786
787         return n;
788 }
789
790 /****************************************************************************
791 write a form struct list
792 ****************************************************************************/
793 int write_ntforms(nt_forms_struct **list, int number)
794 {
795         pstring buf, key;
796         int len;
797         TDB_DATA kbuf,dbuf;
798         int i;
799
800         for (i=0;i<number;i++) {
801                 /* save index, so list is rebuilt in correct order */
802                 len = tdb_pack(buf, sizeof(buf), "dddddddd",
803                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
804                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
805                                (*list)[i].bottom);
806                 if (len > sizeof(buf)) break;
807                 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
808                 kbuf.dsize = strlen(key)+1;
809                 kbuf.dptr = key;
810                 dbuf.dsize = len;
811                 dbuf.dptr = buf;
812                 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
813        }
814
815        return i;
816 }
817
818 /****************************************************************************
819 add a form struct at the end of the list
820 ****************************************************************************/
821 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
822 {
823         int n=0;
824         BOOL update;
825         fstring form_name;
826         nt_forms_struct *tl;
827
828         /*
829          * NT tries to add forms even when
830          * they are already in the base
831          * only update the values if already present
832          */
833
834         update=False;
835         
836         unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
837         for (n=0; n<*count; n++) {
838                 if ( strequal((*list)[n].name, form_name) ) {
839                         update=True;
840                         break;
841                 }
842         }
843
844         if (update==False) {
845                 if((tl=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
846                         DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
847                         return False;
848                 }
849                 *list = tl;
850                 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
851                 (*count)++;
852         }
853         
854         (*list)[n].flag=form->flags;
855         (*list)[n].width=form->size_x;
856         (*list)[n].length=form->size_y;
857         (*list)[n].left=form->left;
858         (*list)[n].top=form->top;
859         (*list)[n].right=form->right;
860         (*list)[n].bottom=form->bottom;
861
862         DEBUG(6,("add_a_form: Successfully %s form [%s]\n", 
863                 update ? "updated" : "added", form_name));
864
865         return True;
866 }
867
868 /****************************************************************************
869  Delete a named form struct.
870 ****************************************************************************/
871
872 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
873 {
874         pstring key;
875         TDB_DATA kbuf;
876         int n=0;
877         fstring form_name;
878
879         *ret = WERR_OK;
880
881         unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
882
883         for (n=0; n<*count; n++) {
884                 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
885                         DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
886                         break;
887                 }
888         }
889
890         if (n == *count) {
891                 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
892                 *ret = WERR_INVALID_PARAM;
893                 return False;
894         }
895
896         slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
897         kbuf.dsize = strlen(key)+1;
898         kbuf.dptr = key;
899         if (tdb_delete(tdb_forms, kbuf) != 0) {
900                 *ret = WERR_NOMEM;
901                 return False;
902         }
903
904         return True;
905 }
906
907 /****************************************************************************
908  Update a form struct.
909 ****************************************************************************/
910
911 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
912 {
913         int n=0;
914         fstring form_name;
915         unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
916
917         DEBUG(106, ("[%s]\n", form_name));
918         for (n=0; n<count; n++) {
919                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
920                 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
921                         break;
922         }
923
924         if (n==count) return;
925
926         (*list)[n].flag=form->flags;
927         (*list)[n].width=form->size_x;
928         (*list)[n].length=form->size_y;
929         (*list)[n].left=form->left;
930         (*list)[n].top=form->top;
931         (*list)[n].right=form->right;
932         (*list)[n].bottom=form->bottom;
933 }
934
935 /****************************************************************************
936  Get the nt drivers list.
937  Traverse the database and look-up the matching names.
938 ****************************************************************************/
939 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
940 {
941         int total=0;
942         const char *short_archi;
943         fstring *fl;
944         pstring key;
945         TDB_DATA kbuf, newkey;
946
947         short_archi = get_short_archi(architecture);
948         slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
949
950         for (kbuf = tdb_firstkey(tdb_drivers);
951              kbuf.dptr;
952              newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
953
954                 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
955                         continue;
956                 
957                 if((fl = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
958                         DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
959                         return -1;
960                 }
961                 else *list = fl;
962
963                 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
964                 total++;
965         }
966
967         return(total);
968 }
969
970 /****************************************************************************
971 function to do the mapping between the long architecture name and
972 the short one.
973 ****************************************************************************/
974 const char *get_short_archi(const char *long_archi)
975 {
976         int i=-1;
977
978         DEBUG(107,("Getting architecture dependant directory\n"));
979         do {
980                 i++;
981         } while ( (archi_table[i].long_archi!=NULL ) &&
982                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
983
984         if (archi_table[i].long_archi==NULL) {
985                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
986                 return NULL;
987         }
988
989         /* this might be client code - but shouldn't this be an fstrcpy etc? */
990
991
992         DEBUGADD(108,("index: [%d]\n", i));
993         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
994         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
995
996         return archi_table[i].short_archi;
997 }
998
999 /****************************************************************************
1000  Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1001  There are two case to be covered here: PE (Portable Executable) and NE (New
1002  Executable) files. Both files support the same INFO structure, but PE files
1003  store the signature in unicode, and NE files store it as !unicode.
1004  returns -1 on error, 1 on version info found, and 0 on no version info found.
1005 ****************************************************************************/
1006
1007 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1008 {
1009         int     i;
1010         char    *buf = NULL;
1011         ssize_t byte_count;
1012
1013         if ((buf=SMB_MALLOC(PE_HEADER_SIZE)) == NULL) {
1014                 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
1015                                 fname, PE_HEADER_SIZE));
1016                 goto error_exit;
1017         }
1018
1019         /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
1020         if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1021                 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1022                          fname, (unsigned long)byte_count));
1023                 goto no_version_info;
1024         }
1025
1026         /* Is this really a DOS header? */
1027         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1028                 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1029                                 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1030                 goto no_version_info;
1031         }
1032
1033         /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1034         if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1035                 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1036                                 fname, errno));
1037                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1038                 goto no_version_info;
1039         }
1040
1041         if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
1042                 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1043                          fname, (unsigned long)byte_count));
1044                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1045                 goto no_version_info;
1046         }
1047
1048         /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1049         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1050                 unsigned int num_sections;
1051                 unsigned int section_table_bytes;
1052                 
1053                 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
1054                         DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
1055                                         fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
1056                         /* At this point, we assume the file is in error. It still could be somthing
1057                          * else besides a PE file, but it unlikely at this point.
1058                          */
1059                         goto error_exit;
1060                 }
1061
1062                 /* get the section table */
1063                 num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1064                 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1065                 if (section_table_bytes == 0)
1066                         goto error_exit;
1067
1068                 SAFE_FREE(buf);
1069                 if ((buf=SMB_MALLOC(section_table_bytes)) == NULL) {
1070                         DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1071                                         fname, section_table_bytes));
1072                         goto error_exit;
1073                 }
1074
1075                 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1076                         DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1077                                  fname, (unsigned long)byte_count));
1078                         goto error_exit;
1079                 }
1080
1081                 /* Iterate the section table looking for the resource section ".rsrc" */
1082                 for (i = 0; i < num_sections; i++) {
1083                         int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1084
1085                         if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1086                                 unsigned int section_pos   = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1087                                 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1088
1089                                 if (section_bytes == 0)
1090                                         goto error_exit;
1091
1092                                 SAFE_FREE(buf);
1093                                 if ((buf=SMB_MALLOC(section_bytes)) == NULL) {
1094                                         DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1095                                                         fname, section_bytes));
1096                                         goto error_exit;
1097                                 }
1098
1099                                 /* Seek to the start of the .rsrc section info */
1100                                 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1101                                         DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1102                                                         fname, errno));
1103                                         goto error_exit;
1104                                 }
1105
1106                                 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1107                                         DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1108                                                  fname, (unsigned long)byte_count));
1109                                         goto error_exit;
1110                                 }
1111
1112                                 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1113                                         goto error_exit;
1114
1115                                 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1116                                         /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1117                                         if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1118                                                 /* Align to next long address */
1119                                                 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1120
1121                                                 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1122                                                         *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1123                                                         *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1124                                                         
1125                                                         DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1126                                                                           fname, *major, *minor,
1127                                                                           (*major>>16)&0xffff, *major&0xffff,
1128                                                                           (*minor>>16)&0xffff, *minor&0xffff));
1129                                                         SAFE_FREE(buf);
1130                                                         return 1;
1131                                                 }
1132                                         }
1133                                 }
1134                         }
1135                 }
1136
1137                 /* Version info not found, fall back to origin date/time */
1138                 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1139                 SAFE_FREE(buf);
1140                 return 0;
1141
1142         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1143                 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1144                         DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1145                                         fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1146                         /* At this point, we assume the file is in error. It still could be somthing
1147                          * else besides a NE file, but it unlikely at this point. */
1148                         goto error_exit;
1149                 }
1150
1151                 /* Allocate a bit more space to speed up things */
1152                 SAFE_FREE(buf);
1153                 if ((buf=SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1154                         DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes  = %d\n",
1155                                         fname, PE_HEADER_SIZE));
1156                         goto error_exit;
1157                 }
1158
1159                 /* This is a HACK! I got tired of trying to sort through the messy
1160                  * 'NE' file format. If anyone wants to clean this up please have at
1161                  * it, but this works. 'NE' files will eventually fade away. JRR */
1162                 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1163                         /* Cover case that should not occur in a well formed 'NE' .dll file */
1164                         if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1165
1166                         for(i=0; i<byte_count; i++) {
1167                                 /* Fast skip past data that can't possibly match */
1168                                 if (buf[i] != 'V') continue;
1169
1170                                 /* Potential match data crosses buf boundry, move it to beginning
1171                                  * of buf, and fill the buf with as much as it will hold. */
1172                                 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1173                                         int bc;
1174
1175                                         memcpy(buf, &buf[i], byte_count-i);
1176                                         if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1177                                                                    (byte_count-i))) < 0) {
1178
1179                                                 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1180                                                                  fname, errno));
1181                                                 goto error_exit;
1182                                         }
1183
1184                                         byte_count = bc + (byte_count - i);
1185                                         if (byte_count<VS_VERSION_INFO_SIZE) break;
1186
1187                                         i = 0;
1188                                 }
1189
1190                                 /* Check that the full signature string and the magic number that
1191                                  * follows exist (not a perfect solution, but the chances that this
1192                                  * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1193                                  * twice, as it is simpler to read the code. */
1194                                 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1195                                         /* Compute skip alignment to next long address */
1196                                         int skip = -(SMB_VFS_LSEEK(fsp, fsp->fh->fd, 0, SEEK_CUR) - (byte_count - i) +
1197                                                                  sizeof(VS_SIGNATURE)) & 3;
1198                                         if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1199
1200                                         *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1201                                         *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1202                                         DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1203                                                           fname, *major, *minor,
1204                                                           (*major>>16)&0xffff, *major&0xffff,
1205                                                           (*minor>>16)&0xffff, *minor&0xffff));
1206                                         SAFE_FREE(buf);
1207                                         return 1;
1208                                 }
1209                         }
1210                 }
1211
1212                 /* Version info not found, fall back to origin date/time */
1213                 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1214                 SAFE_FREE(buf);
1215                 return 0;
1216
1217         } else
1218                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1219                 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1220                                 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1221
1222         no_version_info:
1223                 SAFE_FREE(buf);
1224                 return 0;
1225
1226         error_exit:
1227                 SAFE_FREE(buf);
1228                 return -1;
1229 }
1230
1231 /****************************************************************************
1232 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1233 share one or more files. During the MS installation process files are checked
1234 to insure that only a newer version of a shared file is installed over an
1235 older version. There are several possibilities for this comparison. If there
1236 is no previous version, the new one is newer (obviously). If either file is
1237 missing the version info structure, compare the creation date (on Unix use
1238 the modification date). Otherwise chose the numerically larger version number.
1239 ****************************************************************************/
1240
1241 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1242 {
1243         BOOL   use_version = True;
1244         pstring filepath;
1245
1246         uint32 new_major;
1247         uint32 new_minor;
1248         time_t new_create_time;
1249
1250         uint32 old_major;
1251         uint32 old_minor;
1252         time_t old_create_time;
1253
1254         files_struct    *fsp = NULL;
1255         SMB_STRUCT_STAT st;
1256         SMB_STRUCT_STAT stat_buf;
1257         BOOL bad_path;
1258
1259         SET_STAT_INVALID(st);
1260         SET_STAT_INVALID(stat_buf);
1261         new_create_time = (time_t)0;
1262         old_create_time = (time_t)0;
1263
1264         /* Get file version info (if available) for previous file (if it exists) */
1265         pstrcpy(filepath, old_file);
1266
1267         driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1268
1269         fsp = open_file_ntcreate(conn, filepath, &stat_buf,
1270                                 FILE_GENERIC_READ,
1271                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1272                                 FILE_OPEN,
1273                                 0,
1274                                 FILE_ATTRIBUTE_NORMAL,
1275                                 INTERNAL_OPEN_ONLY,
1276                                 NULL);
1277
1278         if (!fsp) {
1279                 /* Old file not found, so by definition new file is in fact newer */
1280                 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1281                                 filepath, errno));
1282                 return True;
1283
1284         } else {
1285                 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1286                 if (ret == -1) {
1287                         goto error_exit;
1288                 }
1289
1290                 if (!ret) {
1291                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1292                                          old_file));
1293                         use_version = False;
1294                         if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1295                         old_create_time = st.st_mtime;
1296                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1297                 }
1298         }
1299         close_file(fsp, True);
1300
1301         /* Get file version info (if available) for new file */
1302         pstrcpy(filepath, new_file);
1303         driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1304
1305         fsp = open_file_ntcreate(conn, filepath, &stat_buf,
1306                                 FILE_GENERIC_READ,
1307                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1308                                 FILE_OPEN,
1309                                 0,
1310                                 FILE_ATTRIBUTE_NORMAL,
1311                                 INTERNAL_OPEN_ONLY,
1312                                 NULL);
1313
1314         if (!fsp) {
1315                 /* New file not found, this shouldn't occur if the caller did its job */
1316                 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1317                                 filepath, errno));
1318                 goto error_exit;
1319
1320         } else {
1321                 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1322                 if (ret == -1) {
1323                         goto error_exit;
1324                 }
1325
1326                 if (!ret) {
1327                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1328                                          new_file));
1329                         use_version = False;
1330                         if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1331                         new_create_time = st.st_mtime;
1332                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1333                 }
1334         }
1335         close_file(fsp, True);
1336
1337         if (use_version && (new_major != old_major || new_minor != old_minor)) {
1338                 /* Compare versions and choose the larger version number */
1339                 if (new_major > old_major ||
1340                         (new_major == old_major && new_minor > old_minor)) {
1341                         
1342                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1343                         return True;
1344                 }
1345                 else {
1346                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1347                         return False;
1348                 }
1349
1350         } else {
1351                 /* Compare modification time/dates and choose the newest time/date */
1352                 if (new_create_time > old_create_time) {
1353                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1354                         return True;
1355                 }
1356                 else {
1357                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1358                         return False;
1359                 }
1360         }
1361
1362         error_exit:
1363                 if(fsp)
1364                         close_file(fsp, True);
1365                 return -1;
1366 }
1367
1368 /****************************************************************************
1369 Determine the correct cVersion associated with an architecture and driver
1370 ****************************************************************************/
1371 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1372                                    struct current_user *user, WERROR *perr)
1373 {
1374         int               cversion;
1375         NTSTATUS          nt_status;
1376         pstring           driverpath;
1377         DATA_BLOB         null_pw;
1378         fstring           res_type;
1379         files_struct      *fsp = NULL;
1380         BOOL              bad_path;
1381         SMB_STRUCT_STAT   st;
1382         connection_struct *conn;
1383
1384         SET_STAT_INVALID(st);
1385
1386         *perr = WERR_INVALID_PARAM;
1387
1388         /* If architecture is Windows 95/98/ME, the version is always 0. */
1389         if (strcmp(architecture, "WIN40") == 0) {
1390                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1391                 *perr = WERR_OK;
1392                 return 0;
1393         }
1394
1395         /*
1396          * Connect to the print$ share under the same account as the user connected
1397          * to the rpc pipe. Note we must still be root to do this.
1398          */
1399
1400         /* Null password is ok - we are already an authenticated user... */
1401         null_pw = data_blob(NULL, 0);
1402         fstrcpy(res_type, "A:");
1403         become_root();
1404         conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1405         unbecome_root();
1406
1407         if (conn == NULL) {
1408                 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1409                 *perr = ntstatus_to_werror(nt_status);
1410                 return -1;
1411         }
1412
1413         /* We are temporarily becoming the connection user. */
1414         if (!become_user(conn, user->vuid)) {
1415                 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1416                 *perr = WERR_ACCESS_DENIED;
1417                 return -1;
1418         }
1419
1420         /* Open the driver file (Portable Executable format) and determine the
1421          * deriver the cversion. */
1422         slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1423
1424         driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
1425
1426         if ( !vfs_file_exist( conn, driverpath, &st ) ) {
1427                 *perr = WERR_BADFILE;
1428                 goto error_exit;
1429         }
1430
1431         fsp = open_file_ntcreate(conn, driverpath, &st,
1432                                 FILE_GENERIC_READ,
1433                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1434                                 FILE_OPEN,
1435                                 0,
1436                                 FILE_ATTRIBUTE_NORMAL,
1437                                 INTERNAL_OPEN_ONLY,
1438                                 NULL);
1439
1440         if (!fsp) {
1441                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1442                                 driverpath, errno));
1443                 *perr = WERR_ACCESS_DENIED;
1444                 goto error_exit;
1445         } else {
1446                 uint32 major;
1447                 uint32 minor;
1448                 int    ret = get_file_version(fsp, driverpath, &major, &minor);
1449                 if (ret == -1) goto error_exit;
1450
1451                 if (!ret) {
1452                         DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1453                         goto error_exit;
1454                 }
1455
1456                 /*
1457                  * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1458                  * for more details. Version in this case is not just the version of the 
1459                  * file, but the version in the sense of kernal mode (2) vs. user mode
1460                  * (3) drivers. Other bits of the version fields are the version info. 
1461                  * JRR 010716
1462                 */
1463                 cversion = major & 0x0000ffff;
1464                 switch (cversion) {
1465                         case 2: /* WinNT drivers */
1466                         case 3: /* Win2K drivers */
1467                                 break;
1468                         
1469                         default:
1470                                 DEBUG(6,("get_correct_cversion: cversion invalid [%s]  cversion = %d\n", 
1471                                         driverpath, cversion));
1472                                 goto error_exit;
1473                 }
1474
1475                 DEBUG(10,("get_correct_cversion: Version info found [%s]  major = 0x%x  minor = 0x%x\n",
1476                                   driverpath, major, minor));
1477         }
1478
1479         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1480                 driverpath, cversion));
1481
1482         close_file(fsp, True);
1483         close_cnum(conn, user->vuid);
1484         unbecome_user();
1485         *perr = WERR_OK;
1486         return cversion;
1487
1488
1489   error_exit:
1490
1491         if(fsp)
1492                 close_file(fsp, True);
1493
1494         close_cnum(conn, user->vuid);
1495         unbecome_user();
1496         return -1;
1497 }
1498
1499 /****************************************************************************
1500 ****************************************************************************/
1501 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1502                                                                                          struct current_user *user)
1503 {
1504         const char *architecture;
1505         fstring new_name;
1506         char *p;
1507         int i;
1508         WERROR err;
1509
1510         /* clean up the driver name.
1511          * we can get .\driver.dll
1512          * or worse c:\windows\system\driver.dll !
1513          */
1514         /* using an intermediate string to not have overlaping memcpy()'s */
1515         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1516                 fstrcpy(new_name, p+1);
1517                 fstrcpy(driver->driverpath, new_name);
1518         }
1519
1520         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1521                 fstrcpy(new_name, p+1);
1522                 fstrcpy(driver->datafile, new_name);
1523         }
1524
1525         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1526                 fstrcpy(new_name, p+1);
1527                 fstrcpy(driver->configfile, new_name);
1528         }
1529
1530         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1531                 fstrcpy(new_name, p+1);
1532                 fstrcpy(driver->helpfile, new_name);
1533         }
1534
1535         if (driver->dependentfiles) {
1536                 for (i=0; *driver->dependentfiles[i]; i++) {
1537                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1538                                 fstrcpy(new_name, p+1);
1539                                 fstrcpy(driver->dependentfiles[i], new_name);
1540                         }
1541                 }
1542         }
1543
1544         architecture = get_short_archi(driver->environment);
1545         
1546         /* jfm:7/16/2000 the client always sends the cversion=0.
1547          * The server should check which version the driver is by reading
1548          * the PE header of driver->driverpath.
1549          *
1550          * For Windows 95/98 the version is 0 (so the value sent is correct)
1551          * For Windows NT (the architecture doesn't matter)
1552          *      NT 3.1: cversion=0
1553          *      NT 3.5/3.51: cversion=1
1554          *      NT 4: cversion=2
1555          *      NT2K: cversion=3
1556          */
1557         if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1558                         return err;
1559
1560         return WERR_OK;
1561 }
1562         
1563 /****************************************************************************
1564 ****************************************************************************/
1565 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1566 {
1567         const char *architecture;
1568         fstring new_name;
1569         char *p;
1570         int i;
1571         WERROR err;
1572
1573         /* clean up the driver name.
1574          * we can get .\driver.dll
1575          * or worse c:\windows\system\driver.dll !
1576          */
1577         /* using an intermediate string to not have overlaping memcpy()'s */
1578         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1579                 fstrcpy(new_name, p+1);
1580                 fstrcpy(driver->driverpath, new_name);
1581         }
1582
1583         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1584                 fstrcpy(new_name, p+1);
1585                 fstrcpy(driver->datafile, new_name);
1586         }
1587
1588         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1589                 fstrcpy(new_name, p+1);
1590                 fstrcpy(driver->configfile, new_name);
1591         }
1592
1593         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1594                 fstrcpy(new_name, p+1);
1595                 fstrcpy(driver->helpfile, new_name);
1596         }
1597
1598         if (driver->dependentfiles) {
1599                 for (i=0; *driver->dependentfiles[i]; i++) {
1600                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1601                                 fstrcpy(new_name, p+1);
1602                                 fstrcpy(driver->dependentfiles[i], new_name);
1603                         }
1604                 }
1605         }
1606
1607         architecture = get_short_archi(driver->environment);
1608
1609         /* jfm:7/16/2000 the client always sends the cversion=0.
1610          * The server should check which version the driver is by reading
1611          * the PE header of driver->driverpath.
1612          *
1613          * For Windows 95/98 the version is 0 (so the value sent is correct)
1614          * For Windows NT (the architecture doesn't matter)
1615          *      NT 3.1: cversion=0
1616          *      NT 3.5/3.51: cversion=1
1617          *      NT 4: cversion=2
1618          *      NT2K: cversion=3
1619          */
1620
1621         if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1622                         return err;
1623
1624         return WERR_OK;
1625 }
1626
1627 /****************************************************************************
1628 ****************************************************************************/
1629 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1630                                                           uint32 level, struct current_user *user)
1631 {
1632         switch (level) {
1633                 case 3:
1634                 {
1635                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1636                         driver=driver_abstract.info_3;
1637                         return clean_up_driver_struct_level_3(driver, user);
1638                 }
1639                 case 6:
1640                 {
1641                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1642                         driver=driver_abstract.info_6;
1643                         return clean_up_driver_struct_level_6(driver, user);
1644                 }
1645                 default:
1646                         return WERR_INVALID_PARAM;
1647         }
1648 }
1649
1650 /****************************************************************************
1651  This function sucks and should be replaced. JRA.
1652 ****************************************************************************/
1653
1654 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1655 {
1656     dst->cversion  = src->version;
1657
1658     fstrcpy( dst->name, src->name);
1659     fstrcpy( dst->environment, src->environment);
1660     fstrcpy( dst->driverpath, src->driverpath);
1661     fstrcpy( dst->datafile, src->datafile);
1662     fstrcpy( dst->configfile, src->configfile);
1663     fstrcpy( dst->helpfile, src->helpfile);
1664     fstrcpy( dst->monitorname, src->monitorname);
1665     fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1666     dst->dependentfiles = src->dependentfiles;
1667 }
1668
1669 #if 0 /* Debugging function */
1670
1671 static char* ffmt(unsigned char *c){
1672         int i;
1673         static char ffmt_str[17];
1674
1675         for (i=0; i<16; i++) {
1676                 if ((c[i] < ' ') || (c[i] > '~'))
1677                         ffmt_str[i]='.';
1678                 else
1679                         ffmt_str[i]=c[i];
1680         }
1681     ffmt_str[16]='\0';
1682         return ffmt_str;
1683 }
1684
1685 #endif
1686
1687 /****************************************************************************
1688 ****************************************************************************/
1689 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, 
1690                                   struct current_user *user, WERROR *perr)
1691 {
1692         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1693         NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1694         const char *architecture;
1695         pstring new_dir;
1696         pstring old_name;
1697         pstring new_name;
1698         DATA_BLOB null_pw;
1699         connection_struct *conn;
1700         NTSTATUS nt_status;
1701         pstring inbuf;
1702         pstring outbuf;
1703         fstring res_type;
1704         BOOL bad_path;
1705         SMB_STRUCT_STAT st;
1706         int ver = 0;
1707         int i;
1708         int err;
1709
1710         memset(inbuf, '\0', sizeof(inbuf));
1711         memset(outbuf, '\0', sizeof(outbuf));
1712         *perr = WERR_OK;
1713
1714         if (level==3)
1715                 driver=driver_abstract.info_3;
1716         else if (level==6) {
1717                 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1718                 driver = &converted_driver;
1719         } else {
1720                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1721                 return WERR_UNKNOWN_LEVEL;
1722         }
1723
1724         architecture = get_short_archi(driver->environment);
1725
1726         /*
1727          * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1728          * Note we must be root to do this.
1729          */
1730
1731         null_pw = data_blob(NULL, 0);
1732         fstrcpy(res_type, "A:");
1733         become_root();
1734         conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1735         unbecome_root();
1736
1737         if (conn == NULL) {
1738                 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1739                 *perr = ntstatus_to_werror(nt_status);
1740                 return WERR_NO_SUCH_SHARE;
1741         }
1742
1743         /*
1744          * Save who we are - we are temporarily becoming the connection user.
1745          */
1746
1747         if (!become_user(conn, conn->vuid)) {
1748                 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1749                 return WERR_ACCESS_DENIED;
1750         }
1751
1752         /*
1753          * make the directories version and version\driver_name
1754          * under the architecture directory.
1755          */
1756         DEBUG(5,("Creating first directory\n"));
1757         slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1758         driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
1759         mkdir_internal(conn, new_dir, bad_path);
1760
1761         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1762          * listed for this driver which has already been moved, skip it (note:
1763          * drivers may list the same file name several times. Then check if the
1764          * file already exists in archi\cversion\, if so, check that the version
1765          * info (or time stamps if version info is unavailable) is newer (or the
1766          * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1767          * Otherwise, delete the file.
1768          *
1769          * If a file is not moved to archi\cversion\ because of an error, all the
1770          * rest of the 'unmoved' driver files are removed from archi\. If one or
1771          * more of the driver's files was already moved to archi\cversion\, it
1772          * potentially leaves the driver in a partially updated state. Version
1773          * trauma will most likely occur if an client attempts to use any printer
1774          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1775          * done is appropriate... later JRR
1776          */
1777
1778         DEBUG(5,("Moving files now !\n"));
1779
1780         if (driver->driverpath && strlen(driver->driverpath)) {
1781                 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);      
1782                 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);   
1783                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1784                         driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1785                         if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1786                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1787                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1788                                                 new_name, old_name));
1789                                 *perr = WERR_ACCESS_DENIED;
1790                                 ver = -1;
1791                         }
1792                 } 
1793         }
1794
1795         if (driver->datafile && strlen(driver->datafile)) {
1796                 if (!strequal(driver->datafile, driver->driverpath)) {
1797                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);        
1798                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);     
1799                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1800                                 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1801                                 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1802                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1803                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1804                                                         new_name, old_name));
1805                                         *perr = WERR_ACCESS_DENIED;
1806                                         ver = -1;
1807                                 }
1808                         }
1809                 }
1810         }
1811
1812         if (driver->configfile && strlen(driver->configfile)) {
1813                 if (!strequal(driver->configfile, driver->driverpath) &&
1814                         !strequal(driver->configfile, driver->datafile)) {
1815                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);      
1816                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);   
1817                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1818                                 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1819                                 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1820                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1821                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1822                                                         new_name, old_name));
1823                                         *perr = WERR_ACCESS_DENIED;
1824                                         ver = -1;
1825                                 }
1826                         }
1827                 }
1828         }
1829
1830         if (driver->helpfile && strlen(driver->helpfile)) {
1831                 if (!strequal(driver->helpfile, driver->driverpath) &&
1832                         !strequal(driver->helpfile, driver->datafile) &&
1833                         !strequal(driver->helpfile, driver->configfile)) {
1834                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);        
1835                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);     
1836                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1837                                 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1838                                 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1839                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1840                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1841                                                         new_name, old_name));
1842                                         *perr = WERR_ACCESS_DENIED;
1843                                         ver = -1;
1844                                 }
1845                         }
1846                 }
1847         }
1848
1849         if (driver->dependentfiles) {
1850                 for (i=0; *driver->dependentfiles[i]; i++) {
1851                         if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1852                                 !strequal(driver->dependentfiles[i], driver->datafile) &&
1853                                 !strequal(driver->dependentfiles[i], driver->configfile) &&
1854                                 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1855                                 int j;
1856                                 for (j=0; j < i; j++) {
1857                                         if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1858                                                 goto NextDriver;
1859                                         }
1860                                 }
1861
1862                                 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);       
1863                                 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);    
1864                                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1865                                         driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1866                                         if ( !copy_file(new_name, old_name, conn,
1867                                                         OPENX_FILE_EXISTS_TRUNCATE|
1868                                                         OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1869                                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1870                                                                 new_name, old_name));
1871                                                 *perr = WERR_ACCESS_DENIED;
1872                                                 ver = -1;
1873                                         }
1874                                 }
1875                         }
1876                 NextDriver: ;
1877                 }
1878         }
1879
1880         close_cnum(conn, user->vuid);
1881         unbecome_user();
1882
1883         return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
1884 }
1885
1886 /****************************************************************************
1887 ****************************************************************************/
1888 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1889 {
1890         int len, buflen;
1891         const char *architecture;
1892         pstring directory;
1893         fstring temp_name;
1894         pstring key;
1895         char *buf;
1896         int i, ret;
1897         TDB_DATA kbuf, dbuf;
1898
1899         architecture = get_short_archi(driver->environment);
1900
1901         /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1902          * \\server is added in the rpc server layer.
1903          * It does make sense to NOT store the server's name in the printer TDB.
1904          */
1905
1906         slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1907
1908         /* .inf files do not always list a file for each of the four standard files. 
1909          * Don't prepend a path to a null filename, or client claims:
1910          *   "The server on which the printer resides does not have a suitable 
1911          *   <printer driver name> printer driver installed. Click OK if you 
1912          *   wish to install the driver on your local machine."
1913          */
1914         if (strlen(driver->driverpath)) {
1915                 fstrcpy(temp_name, driver->driverpath);
1916                 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1917         }
1918
1919         if (strlen(driver->datafile)) {
1920                 fstrcpy(temp_name, driver->datafile);
1921                 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1922         }
1923
1924         if (strlen(driver->configfile)) {
1925                 fstrcpy(temp_name, driver->configfile);
1926                 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1927         }
1928
1929         if (strlen(driver->helpfile)) {
1930                 fstrcpy(temp_name, driver->helpfile);
1931                 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1932         }
1933
1934         if (driver->dependentfiles) {
1935                 for (i=0; *driver->dependentfiles[i]; i++) {
1936                         fstrcpy(temp_name, driver->dependentfiles[i]);
1937                         slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1938                 }
1939         }
1940
1941         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1942
1943         DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1944
1945         buf = NULL;
1946         len = buflen = 0;
1947
1948  again:
1949         len = 0;
1950         len += tdb_pack(buf+len, buflen-len, "dffffffff",
1951                         driver->cversion,
1952                         driver->name,
1953                         driver->environment,
1954                         driver->driverpath,
1955                         driver->datafile,
1956                         driver->configfile,
1957                         driver->helpfile,
1958                         driver->monitorname,
1959                         driver->defaultdatatype);
1960
1961         if (driver->dependentfiles) {
1962                 for (i=0; *driver->dependentfiles[i]; i++) {
1963                         len += tdb_pack(buf+len, buflen-len, "f",
1964                                         driver->dependentfiles[i]);
1965                 }
1966         }
1967
1968         if (len != buflen) {
1969                 char *tb;
1970
1971                 tb = (char *)SMB_REALLOC(buf, len);
1972                 if (!tb) {
1973                         DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1974                         ret = -1;
1975                         goto done;
1976                 }
1977                 else buf = tb;
1978                 buflen = len;
1979                 goto again;
1980         }
1981
1982
1983         kbuf.dptr = key;
1984         kbuf.dsize = strlen(key)+1;
1985         dbuf.dptr = buf;
1986         dbuf.dsize = len;
1987         
1988         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1989
1990 done:
1991         if (ret)
1992                 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1993
1994         SAFE_FREE(buf);
1995         return ret;
1996 }
1997
1998 /****************************************************************************
1999 ****************************************************************************/
2000 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2001 {
2002         NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2003
2004         ZERO_STRUCT(info3);
2005         info3.cversion = driver->version;
2006         fstrcpy(info3.name,driver->name);
2007         fstrcpy(info3.environment,driver->environment);
2008         fstrcpy(info3.driverpath,driver->driverpath);
2009         fstrcpy(info3.datafile,driver->datafile);
2010         fstrcpy(info3.configfile,driver->configfile);
2011         fstrcpy(info3.helpfile,driver->helpfile);
2012         fstrcpy(info3.monitorname,driver->monitorname);
2013         fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2014         info3.dependentfiles = driver->dependentfiles;
2015
2016         return add_a_printer_driver_3(&info3);
2017 }
2018
2019
2020 /****************************************************************************
2021 ****************************************************************************/
2022 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2023 {
2024         NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2025
2026         ZERO_STRUCT(info);
2027
2028         fstrcpy(info.name, driver);
2029         fstrcpy(info.defaultdatatype, "RAW");
2030         
2031         fstrcpy(info.driverpath, "");
2032         fstrcpy(info.datafile, "");
2033         fstrcpy(info.configfile, "");
2034         fstrcpy(info.helpfile, "");
2035
2036         if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2037                 return WERR_NOMEM;
2038
2039         memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2040         fstrcpy(info.dependentfiles[0], "");
2041
2042         *info_ptr = memdup(&info, sizeof(info));
2043         
2044         return WERR_OK;
2045 }
2046
2047 /****************************************************************************
2048 ****************************************************************************/
2049 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
2050 {
2051         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2052         TDB_DATA kbuf, dbuf;
2053         const char *architecture;
2054         int len = 0;
2055         int i;
2056         pstring key;
2057
2058         ZERO_STRUCT(driver);
2059
2060         architecture = get_short_archi(arch);
2061
2062         if ( !architecture )
2063                 return WERR_UNKNOWN_PRINTER_DRIVER;
2064         
2065         /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2066         
2067         if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2068                 version = 0;
2069
2070         DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2071
2072         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
2073
2074         kbuf.dptr = key;
2075         kbuf.dsize = strlen(key)+1;
2076         
2077         dbuf = tdb_fetch(tdb_drivers, kbuf);
2078         if (!dbuf.dptr) 
2079                 return WERR_UNKNOWN_PRINTER_DRIVER;
2080
2081         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2082                           &driver.cversion,
2083                           driver.name,
2084                           driver.environment,
2085                           driver.driverpath,
2086                           driver.datafile,
2087                           driver.configfile,
2088                           driver.helpfile,
2089                           driver.monitorname,
2090                           driver.defaultdatatype);
2091
2092         i=0;
2093         while (len < dbuf.dsize) {
2094                 fstring *tddfs;
2095
2096                 tddfs = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2097                 if ( !tddfs ) {
2098                         DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2099                         break;
2100                 }
2101                 else 
2102                         driver.dependentfiles = tddfs;
2103
2104                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2105                                   &driver.dependentfiles[i]);
2106                 i++;
2107         }
2108         
2109         if ( driver.dependentfiles )
2110                 fstrcpy( driver.dependentfiles[i], "" );
2111
2112         SAFE_FREE(dbuf.dptr);
2113
2114         if (len != dbuf.dsize) {
2115                 SAFE_FREE(driver.dependentfiles);
2116
2117                 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2118         }
2119
2120         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2121
2122         return WERR_OK;
2123 }
2124
2125 /****************************************************************************
2126  Debugging function, dump at level 6 the struct in the logs.
2127 ****************************************************************************/
2128
2129 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2130 {
2131         uint32 result;
2132         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2133         int i;
2134         
2135         DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2136         
2137         switch (level)
2138         {
2139                 case 3:
2140                 {
2141                         if (driver.info_3 == NULL)
2142                                 result=5;
2143                         else {
2144                                 info3=driver.info_3;
2145                         
2146                                 DEBUGADD(20,("version:[%d]\n",         info3->cversion));
2147                                 DEBUGADD(20,("name:[%s]\n",            info3->name));
2148                                 DEBUGADD(20,("environment:[%s]\n",     info3->environment));
2149                                 DEBUGADD(20,("driverpath:[%s]\n",      info3->driverpath));
2150                                 DEBUGADD(20,("datafile:[%s]\n",        info3->datafile));
2151                                 DEBUGADD(20,("configfile:[%s]\n",      info3->configfile));
2152                                 DEBUGADD(20,("helpfile:[%s]\n",        info3->helpfile));
2153                                 DEBUGADD(20,("monitorname:[%s]\n",     info3->monitorname));
2154                                 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2155                                 
2156                                 for (i=0; info3->dependentfiles &&
2157                                           *info3->dependentfiles[i]; i++) {
2158                                         DEBUGADD(20,("dependentfile:[%s]\n",
2159                                                       info3->dependentfiles[i]));
2160                                 }
2161                                 result=0;
2162                         }
2163                         break;
2164                 }
2165                 default:
2166                         DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2167                         result=1;
2168                         break;
2169         }
2170         
2171         return result;
2172 }
2173
2174 /****************************************************************************
2175 ****************************************************************************/
2176 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
2177 {
2178         int len = 0;
2179
2180         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2181
2182         if (!nt_devmode)
2183                 return len;
2184
2185         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2186                         nt_devmode->devicename,
2187                         nt_devmode->formname,
2188
2189                         nt_devmode->specversion,
2190                         nt_devmode->driverversion,
2191                         nt_devmode->size,
2192                         nt_devmode->driverextra,
2193                         nt_devmode->orientation,
2194                         nt_devmode->papersize,
2195                         nt_devmode->paperlength,
2196                         nt_devmode->paperwidth,
2197                         nt_devmode->scale,
2198                         nt_devmode->copies,
2199                         nt_devmode->defaultsource,
2200                         nt_devmode->printquality,
2201                         nt_devmode->color,
2202                         nt_devmode->duplex,
2203                         nt_devmode->yresolution,
2204                         nt_devmode->ttoption,
2205                         nt_devmode->collate,
2206                         nt_devmode->logpixels,
2207                         
2208                         nt_devmode->fields,
2209                         nt_devmode->bitsperpel,
2210                         nt_devmode->pelswidth,
2211                         nt_devmode->pelsheight,
2212                         nt_devmode->displayflags,
2213                         nt_devmode->displayfrequency,
2214                         nt_devmode->icmmethod,
2215                         nt_devmode->icmintent,
2216                         nt_devmode->mediatype,
2217                         nt_devmode->dithertype,
2218                         nt_devmode->reserved1,
2219                         nt_devmode->reserved2,
2220                         nt_devmode->panningwidth,
2221                         nt_devmode->panningheight,
2222                         nt_devmode->nt_dev_private);
2223
2224         
2225         if (nt_devmode->nt_dev_private) {
2226                 len += tdb_pack(buf+len, buflen-len, "B",
2227                                 nt_devmode->driverextra,
2228                                 nt_devmode->nt_dev_private);
2229         }
2230
2231         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2232
2233         return len;
2234 }
2235
2236 /****************************************************************************
2237  Pack all values in all printer keys
2238  ***************************************************************************/
2239  
2240 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
2241 {
2242         int             len = 0;
2243         int             i, j;
2244         REGISTRY_VALUE  *val;
2245         REGVAL_CTR      *val_ctr;
2246         pstring         path;
2247         int             num_values;
2248
2249         if ( !data )
2250                 return 0;
2251
2252         /* loop over all keys */
2253                 
2254         for ( i=0; i<data->num_keys; i++ ) {    
2255                 val_ctr = data->keys[i].values;
2256                 num_values = regval_ctr_numvals( val_ctr );
2257
2258                 /* pack the keyname followed by a empty value */
2259
2260                 len += tdb_pack(buf+len, buflen-len, "pPdB", 
2261                                 &data->keys[i].name,
2262                                 data->keys[i].name, 
2263                                 REG_NONE,
2264                                 0,
2265                                 NULL);
2266                 
2267                 /* now loop over all values */
2268                 
2269                 for ( j=0; j<num_values; j++ ) {
2270                         /* pathname should be stored as <key>\<value> */
2271                         
2272                         val = regval_ctr_specific_value( val_ctr, j );
2273                         pstrcpy( path, data->keys[i].name );
2274                         pstrcat( path, "\\" );
2275                         pstrcat( path, regval_name(val) );
2276                         
2277                         len += tdb_pack(buf+len, buflen-len, "pPdB",
2278                                         val,
2279                                         path,
2280                                         regval_type(val),
2281                                         regval_size(val),
2282                                         regval_data_p(val) );
2283
2284                         DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2285                 }
2286         
2287         }
2288
2289         /* terminator */
2290         
2291         len += tdb_pack(buf+len, buflen-len, "p", NULL);
2292
2293         return len;
2294 }
2295
2296
2297 /****************************************************************************
2298  Delete a printer - this just deletes the printer info file, any open
2299  handles are not affected.
2300 ****************************************************************************/
2301
2302 uint32 del_a_printer(const char *sharename)
2303 {
2304         pstring key;
2305         TDB_DATA kbuf;
2306         pstring printdb_path;
2307
2308         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2309         kbuf.dptr=key;
2310         kbuf.dsize=strlen(key)+1;
2311         tdb_delete(tdb_printers, kbuf);
2312
2313         slprintf(key, sizeof(key)-1, "%s%s", SECDESC_PREFIX, sharename);
2314         kbuf.dptr=key;
2315         kbuf.dsize=strlen(key)+1;
2316         tdb_delete(tdb_printers, kbuf);
2317
2318         close_all_print_db();
2319
2320         if (geteuid() == 0) {
2321                 pstrcpy(printdb_path, lock_path("printing/"));
2322                 pstrcat(printdb_path, sharename);
2323                 pstrcat(printdb_path, ".tdb");
2324
2325                 unlink(printdb_path);
2326         }
2327
2328         return 0;
2329 }
2330
2331 /****************************************************************************
2332 ****************************************************************************/
2333 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2334 {
2335         char *buf;
2336         int buflen, len;
2337         WERROR ret;
2338         TDB_DATA kbuf, dbuf;
2339         
2340         /*
2341          * in addprinter: no servername and the printer is the name
2342          * in setprinter: servername is \\server
2343          *                and printer is \\server\\printer
2344          *
2345          * Samba manages only local printers.
2346          * we currently don't support things like i
2347          * path=\\other_server\printer
2348          *
2349          * We only store the printername, not \\server\printername
2350          */
2351
2352         if ( info->servername[0] != '\0' ) {
2353                 trim_string(info->printername, info->servername, NULL);
2354                 trim_char(info->printername, '\\', '\0');
2355                 info->servername[0]='\0';
2356         }
2357
2358         /*
2359          * JFM: one day I'll forget.
2360          * below that's info->portname because that's the SAMBA sharename
2361          * and I made NT 'thinks' it's the portname
2362          * the info->sharename is the thing you can name when you add a printer
2363          * that's the short-name when you create shared printer for 95/98
2364          * So I've made a limitation in SAMBA: you can only have 1 printer model
2365          * behind a SAMBA share.
2366          */
2367
2368         buf = NULL;
2369         buflen = 0;
2370
2371  again: 
2372         len = 0;
2373         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2374                         info->attributes,
2375                         info->priority,
2376                         info->default_priority,
2377                         info->starttime,
2378                         info->untiltime,
2379                         info->status,
2380                         info->cjobs,
2381                         info->averageppm,
2382                         info->changeid,
2383                         info->c_setprinter,
2384                         info->setuptime,
2385                         info->servername,
2386                         info->printername,
2387                         info->sharename,
2388                         info->portname,
2389                         info->drivername,
2390                         info->comment,
2391                         info->location,
2392                         info->sepfile,
2393                         info->printprocessor,
2394                         info->datatype,
2395                         info->parameters);
2396
2397         len += pack_devicemode(info->devmode, buf+len, buflen-len);
2398         
2399         len += pack_values( info->data, buf+len, buflen-len );
2400
2401         if (buflen != len) {
2402                 char *tb;
2403
2404                 tb = (char *)SMB_REALLOC(buf, len);
2405                 if (!tb) {
2406                         DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2407                         ret = WERR_NOMEM;
2408                         goto done;
2409                 }
2410                 else buf = tb;
2411                 buflen = len;
2412                 goto again;
2413         }
2414         
2415
2416         kbuf = make_printer_tdbkey( info->sharename );
2417
2418         dbuf.dptr = buf;
2419         dbuf.dsize = len;
2420
2421         ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2422
2423 done:
2424         if (!W_ERROR_IS_OK(ret))
2425                 DEBUG(8, ("error updating printer to tdb on disk\n"));
2426
2427         SAFE_FREE(buf);
2428
2429         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2430                  info->sharename, info->drivername, info->portname, len));
2431
2432         return ret;
2433 }
2434
2435
2436 /****************************************************************************
2437  Malloc and return an NT devicemode.
2438 ****************************************************************************/
2439
2440 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2441 {
2442
2443         char adevice[MAXDEVICENAME];
2444         NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2445
2446         if (nt_devmode == NULL) {
2447                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2448                 return NULL;
2449         }
2450
2451         ZERO_STRUCTP(nt_devmode);
2452
2453         slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2454         fstrcpy(nt_devmode->devicename, adevice);       
2455         
2456         fstrcpy(nt_devmode->formname, "Letter");
2457
2458         nt_devmode->specversion      = 0x0401;
2459         nt_devmode->driverversion    = 0x0400;
2460         nt_devmode->size             = 0x00DC;
2461         nt_devmode->driverextra      = 0x0000;
2462         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY |
2463                                        DEFAULTSOURCE | COPIES | SCALE |
2464                                        PAPERSIZE | ORIENTATION;
2465         nt_devmode->orientation      = 1;
2466         nt_devmode->papersize        = PAPER_LETTER;
2467         nt_devmode->paperlength      = 0;
2468         nt_devmode->paperwidth       = 0;
2469         nt_devmode->scale            = 0x64;
2470         nt_devmode->copies           = 1;
2471         nt_devmode->defaultsource    = BIN_FORMSOURCE;
2472         nt_devmode->printquality     = RES_HIGH;           /* 0x0258 */
2473         nt_devmode->color            = COLOR_MONOCHROME;
2474         nt_devmode->duplex           = DUP_SIMPLEX;
2475         nt_devmode->yresolution      = 0;
2476         nt_devmode->ttoption         = TT_SUBDEV;
2477         nt_devmode->collate          = COLLATE_FALSE;
2478         nt_devmode->icmmethod        = 0;
2479         nt_devmode->icmintent        = 0;
2480         nt_devmode->mediatype        = 0;
2481         nt_devmode->dithertype       = 0;
2482
2483         /* non utilisés par un driver d'imprimante */
2484         nt_devmode->logpixels        = 0;
2485         nt_devmode->bitsperpel       = 0;
2486         nt_devmode->pelswidth        = 0;
2487         nt_devmode->pelsheight       = 0;
2488         nt_devmode->displayflags     = 0;
2489         nt_devmode->displayfrequency = 0;
2490         nt_devmode->reserved1        = 0;
2491         nt_devmode->reserved2        = 0;
2492         nt_devmode->panningwidth     = 0;
2493         nt_devmode->panningheight    = 0;
2494         
2495         nt_devmode->nt_dev_private = NULL;
2496         return nt_devmode;
2497 }
2498
2499 /****************************************************************************
2500  Deepcopy an NT devicemode.
2501 ****************************************************************************/
2502
2503 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2504 {
2505         NT_DEVICEMODE *new_nt_devicemode = NULL;
2506
2507         if ( !nt_devicemode )
2508                 return NULL;
2509
2510         if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2511                 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2512                 return NULL;
2513         }
2514
2515         new_nt_devicemode->nt_dev_private = NULL;
2516         if (nt_devicemode->nt_dev_private != NULL) {
2517                 if ((new_nt_devicemode->nt_dev_private = memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2518                         SAFE_FREE(new_nt_devicemode);
2519                         DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2520                         return NULL;
2521         }
2522         }
2523
2524         return new_nt_devicemode;
2525 }
2526
2527 /****************************************************************************
2528  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2529 ****************************************************************************/
2530
2531 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2532 {
2533         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2534
2535         if(nt_devmode == NULL)
2536                 return;
2537
2538         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2539
2540         SAFE_FREE(nt_devmode->nt_dev_private);
2541         SAFE_FREE(*devmode_ptr);
2542 }
2543
2544 /****************************************************************************
2545  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2546 ****************************************************************************/
2547
2548 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2549 {
2550         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2551
2552         if ( !info )
2553                 return;
2554
2555         free_nt_devicemode(&info->devmode);
2556
2557         TALLOC_FREE( *info_ptr );
2558 }
2559
2560
2561 /****************************************************************************
2562 ****************************************************************************/
2563 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2564 {
2565         int len = 0;
2566         int extra_len = 0;
2567         NT_DEVICEMODE devmode;
2568         
2569         ZERO_STRUCT(devmode);
2570
2571         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2572
2573         if (!*nt_devmode) return len;
2574
2575         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2576                           devmode.devicename,
2577                           devmode.formname,
2578
2579                           &devmode.specversion,
2580                           &devmode.driverversion,
2581                           &devmode.size,
2582                           &devmode.driverextra,
2583                           &devmode.orientation,
2584                           &devmode.papersize,
2585                           &devmode.paperlength,
2586                           &devmode.paperwidth,
2587                           &devmode.scale,
2588                           &devmode.copies,
2589                           &devmode.defaultsource,
2590                           &devmode.printquality,
2591                           &devmode.color,
2592                           &devmode.duplex,
2593                           &devmode.yresolution,
2594                           &devmode.ttoption,
2595                           &devmode.collate,
2596                           &devmode.logpixels,
2597                         
2598                           &devmode.fields,
2599                           &devmode.bitsperpel,
2600                           &devmode.pelswidth,
2601                           &devmode.pelsheight,
2602                           &devmode.displayflags,
2603                           &devmode.displayfrequency,
2604                           &devmode.icmmethod,
2605                           &devmode.icmintent,
2606                           &devmode.mediatype,
2607                           &devmode.dithertype,
2608                           &devmode.reserved1,
2609                           &devmode.reserved2,
2610                           &devmode.panningwidth,
2611                           &devmode.panningheight,
2612                           &devmode.nt_dev_private);
2613         
2614         if (devmode.nt_dev_private) {
2615                 /* the len in tdb_unpack is an int value and
2616                  * devmode.driverextra is only a short
2617                  */
2618                 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2619                 devmode.driverextra=(uint16)extra_len;
2620                 
2621                 /* check to catch an invalid TDB entry so we don't segfault */
2622                 if (devmode.driverextra == 0) {
2623                         devmode.nt_dev_private = NULL;
2624                 }
2625         }
2626
2627         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2628
2629         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2630         if (devmode.nt_dev_private)
2631                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2632
2633         return len;
2634 }
2635
2636 /****************************************************************************
2637  Allocate and initialize a new slot.
2638 ***************************************************************************/
2639  
2640 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2641 {
2642         NT_PRINTER_KEY  *d;
2643         int             key_index;
2644         
2645         if ( !name || !data )
2646                 return -1;
2647
2648         /* allocate another slot in the NT_PRINTER_KEY array */
2649         
2650         if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2651                 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2652                 return -1;
2653         }
2654
2655         data->keys = d;
2656         
2657         key_index = data->num_keys;
2658         
2659         /* initialze new key */
2660         
2661         data->keys[key_index].name = talloc_strdup( data, name );
2662         
2663         if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) ) 
2664                 return -1;
2665         
2666         data->num_keys++;
2667
2668         DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2669         
2670         return key_index;
2671 }
2672
2673 /****************************************************************************
2674  search for a registry key name in the existing printer data
2675  ***************************************************************************/
2676
2677 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2678 {
2679         int i;
2680         
2681         for ( i=0; i<data->num_keys; i++ ) {
2682                 if ( strequal( data->keys[i].name, name ) ) {
2683                 
2684                         /* cleanup memory */
2685                         
2686                         TALLOC_FREE( data->keys[i].name );
2687                         TALLOC_FREE( data->keys[i].values );
2688                         
2689                         /* if not the end of the array, move remaining elements down one slot */
2690                         
2691                         data->num_keys--;
2692                         if ( data->num_keys && (i < data->num_keys) )
2693                                 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2694                                 
2695                         break;
2696                 }
2697         }
2698         
2699
2700         return data->num_keys;
2701 }
2702
2703 /****************************************************************************
2704  search for a registry key name in the existing printer data
2705  ***************************************************************************/
2706  
2707 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2708 {
2709         int             key_index = -1;
2710         int             i;
2711         
2712         if ( !data || !name )
2713                 return -1;
2714
2715         DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2716
2717         /* loop over all existing keys */
2718         
2719         for ( i=0; i<data->num_keys; i++ ) {
2720                 if ( strequal(data->keys[i].name, name) ) {
2721                         DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2722                         key_index = i;
2723                         break;
2724                 
2725                 }
2726         }
2727         
2728         return key_index;
2729 }
2730
2731 /****************************************************************************
2732  ***************************************************************************/
2733
2734 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2735 {
2736         int     i, j;
2737         int     key_len;
2738         int     num_subkeys = 0;
2739         char    *p;
2740         fstring *ptr, *subkeys_ptr = NULL;
2741         fstring subkeyname;
2742         
2743         if ( !data )
2744                 return 0;
2745
2746         if ( !key )
2747                 return -1;
2748
2749         /* special case of asking for the top level printer data registry key names */
2750
2751         if ( strlen(key) == 0 ) {
2752                 for ( i=0; i<data->num_keys; i++ ) {
2753                 
2754                         /* found a match, so allocate space and copy the name */
2755                         
2756                         if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2757                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 
2758                                         num_subkeys+1));
2759                                 SAFE_FREE( subkeys );
2760                                 return -1;
2761                         }
2762                         
2763                         subkeys_ptr = ptr;
2764                         fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2765                         num_subkeys++;
2766                 }
2767
2768                 goto done;
2769         }
2770                 
2771         /* asking for the subkeys of some key */
2772         /* subkey paths are stored in the key name using '\' as the delimiter */
2773
2774         for ( i=0; i<data->num_keys; i++ ) {
2775                 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2776                         
2777                         /* if we found the exact key, then break */
2778                         key_len = strlen( key );
2779                         if ( strlen(data->keys[i].name) == key_len )
2780                                 break;
2781                         
2782                         /* get subkey path */
2783
2784                         p = data->keys[i].name + key_len;
2785                         if ( *p == '\\' )
2786                                 p++;
2787                         fstrcpy( subkeyname, p );
2788                         if ( (p = strchr( subkeyname, '\\' )) )
2789                                 *p = '\0';
2790                         
2791                         /* don't add a key more than once */
2792                         
2793                         for ( j=0; j<num_subkeys; j++ ) {
2794                                 if ( strequal( subkeys_ptr[j], subkeyname ) )
2795                                         break;
2796                         }
2797                         
2798                         if ( j != num_subkeys )
2799                                 continue;
2800
2801                         /* found a match, so allocate space and copy the name */
2802                         
2803                         if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2804                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 
2805                                         num_subkeys+1));
2806                                 SAFE_FREE( subkeys );
2807                                 return 0;
2808                         }
2809                         
2810                         subkeys_ptr = ptr;
2811                         fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2812                         num_subkeys++;
2813                 }
2814                 
2815         }
2816         
2817         /* return error if the key was not found */
2818         
2819         if ( i == data->num_keys )
2820                 return -1;
2821         
2822 done:
2823         /* tag off the end */
2824         
2825         if (num_subkeys)
2826                 fstrcpy(subkeys_ptr[num_subkeys], "" );
2827         
2828         *subkeys = subkeys_ptr;
2829
2830         return num_subkeys;
2831 }
2832
2833 #ifdef HAVE_ADS
2834 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name, 
2835                             const char *sz)
2836 {
2837         smb_ucs2_t conv_str[1024];
2838         size_t str_size;
2839
2840         regval_ctr_delvalue(ctr, val_name);
2841         str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2842                              STR_TERMINATE | STR_NOALIGN);
2843         regval_ctr_addvalue(ctr, val_name, REG_SZ, 
2844                             (char *) conv_str, str_size);
2845 }
2846
2847 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name, 
2848                                uint32 dword)
2849 {
2850         regval_ctr_delvalue(ctr, val_name);
2851         regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2852                             (char *) &dword, sizeof(dword));
2853 }
2854
2855 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2856                               BOOL b)
2857 {
2858         uint8 bin_bool = (b ? 1 : 0);
2859         regval_ctr_delvalue(ctr, val_name);
2860         regval_ctr_addvalue(ctr, val_name, REG_BINARY, 
2861                             (char *) &bin_bool, sizeof(bin_bool));
2862 }
2863
2864 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2865                                          const char *multi_sz)
2866 {
2867         smb_ucs2_t *conv_strs = NULL;
2868         size_t str_size;
2869
2870         /* a multi-sz has to have a null string terminator, i.e., the last
2871            string must be followed by two nulls */
2872         str_size = strlen(multi_sz) + 2;
2873         conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2874         if (!conv_strs) {
2875                 return;
2876         }
2877
2878         /* Change to byte units. */
2879         str_size *= sizeof(smb_ucs2_t);
2880         push_ucs2(NULL, conv_strs, multi_sz, str_size, 
2881                   STR_TERMINATE | STR_NOALIGN);
2882
2883         regval_ctr_delvalue(ctr, val_name);
2884         regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ, 
2885                             (char *) conv_strs, str_size);      
2886         safe_free(conv_strs);
2887         
2888 }
2889
2890 /****************************************************************************
2891  * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2892  *
2893  * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2894  * @return BOOL indicating success or failure
2895  ***************************************************************************/
2896
2897 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2898 {
2899         REGVAL_CTR *ctr = NULL;
2900         fstring longname;
2901         fstring dnssuffix;
2902         char *allocated_string = NULL;
2903         const char *ascii_str;
2904         int i;
2905
2906         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2907                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2908         ctr = info2->data->keys[i].values;
2909
2910         map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2911         map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2912
2913         /* we make the assumption that the netbios name is the same 
2914            as the DNS name sinc ethe former will be what we used to 
2915            join the domain */
2916
2917         if ( get_mydnsdomname( dnssuffix ) )
2918                 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2919         else
2920                 fstrcpy( longname, global_myname() );
2921                 
2922         map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2923
2924         asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2925         map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2926         SAFE_FREE(allocated_string);
2927
2928         map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2929         map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2930         map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2931         map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2932         map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2933         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2934         map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2935         map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2936         map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2937
2938         map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2939                           (info2->attributes & 
2940                            PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2941
2942         switch (info2->attributes & 0x3) {
2943         case 0:
2944                 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2945                 break;
2946         case 1:
2947                 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2948                 break;
2949         case 2:
2950                 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2951                 break;
2952         default:
2953                 ascii_str = "unknown";
2954         }
2955         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2956
2957         return True;
2958 }
2959
2960 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2, 
2961                                struct uuid guid)
2962 {
2963         int i;
2964         REGVAL_CTR *ctr=NULL;
2965
2966         /* find the DsSpooler key */
2967         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2968                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2969         ctr = info2->data->keys[i].values;
2970
2971         regval_ctr_delvalue(ctr, "objectGUID");
2972         regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY, 
2973                             (char *) &guid, sizeof(struct uuid));       
2974 }
2975
2976 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2977                                      NT_PRINTER_INFO_LEVEL *printer)
2978 {
2979         ADS_STATUS ads_rc;
2980         void *res;
2981         char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2982         char *srv_dn_utf8, **srv_cn_utf8;
2983         TALLOC_CTX *ctx;
2984         ADS_MODLIST mods;
2985         const char *attrs[] = {"objectGUID", NULL};
2986         struct uuid guid;
2987         WERROR win_rc = WERR_OK;
2988
2989         DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
2990
2991         /* figure out where to publish */
2992         ads_find_machine_acct(ads, &res, global_myname());
2993
2994         /* We use ldap_get_dn here as we need the answer
2995          * in utf8 to call ldap_explode_dn(). JRA. */
2996
2997         srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2998         if (!srv_dn_utf8) {
2999                 ads_destroy(&ads);
3000                 return WERR_SERVER_UNAVAILABLE;
3001         }
3002         ads_msgfree(ads, res);
3003         srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3004         if (!srv_cn_utf8) {
3005                 ldap_memfree(srv_dn_utf8);
3006                 ads_destroy(&ads);
3007                 return WERR_SERVER_UNAVAILABLE;
3008         }
3009         /* Now convert to CH_UNIX. */
3010         if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
3011                 ldap_memfree(srv_dn_utf8);
3012                 ldap_memfree(srv_cn_utf8);
3013                 ads_destroy(&ads);
3014                 return WERR_SERVER_UNAVAILABLE;
3015         }
3016         if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
3017                 ldap_memfree(srv_dn_utf8);
3018                 ldap_memfree(srv_cn_utf8);
3019                 ads_destroy(&ads);
3020                 SAFE_FREE(srv_dn);
3021                 return WERR_SERVER_UNAVAILABLE;
3022         }
3023
3024         ldap_memfree(srv_dn_utf8);
3025         ldap_memfree(srv_cn_utf8);
3026
3027         asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0, 
3028                  printer->info_2->sharename, srv_dn);
3029
3030         SAFE_FREE(srv_dn);
3031         SAFE_FREE(srv_cn_0);
3032
3033         /* build the ads mods */
3034         ctx = talloc_init("nt_printer_publish_ads");
3035         mods = ads_init_mods(ctx);
3036
3037         get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3038         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, 
3039                     printer->info_2->sharename);
3040
3041         /* publish it */
3042         ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3043         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
3044                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3045
3046         if (!ADS_ERR_OK(ads_rc))
3047                 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3048         
3049         talloc_destroy(ctx);
3050
3051         /* retreive the guid and store it locally */
3052         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3053                 ZERO_STRUCT(guid);
3054                 ads_pull_guid(ads, res, &guid);
3055                 ads_msgfree(ads, res);
3056                 store_printer_guid(printer->info_2, guid);
3057                 win_rc = mod_a_printer(printer, 2);
3058         } 
3059
3060         SAFE_FREE(prt_dn);
3061         return win_rc;
3062 }
3063
3064 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3065                                        NT_PRINTER_INFO_LEVEL *printer)
3066 {
3067         ADS_STATUS ads_rc;
3068         void *res;
3069         char *prt_dn = NULL;
3070
3071         DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3072
3073         /* remove the printer from the directory */
3074         ads_rc = ads_find_printer_on_server(ads, &res, 
3075                             printer->info_2->sharename, global_myname());
3076
3077         if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
3078                 prt_dn = ads_get_dn(ads, res);
3079                 ads_rc = ads_del_dn(ads, prt_dn);
3080                 ads_memfree(ads, prt_dn);
3081         }
3082
3083         ads_msgfree(ads, res);
3084         return WERR_OK;
3085 }
3086
3087 /****************************************************************************
3088  * Publish a printer in the directory
3089  *
3090  * @param snum describing printer service
3091  * @return WERROR indicating status of publishing
3092  ***************************************************************************/
3093
3094 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3095 {
3096         ADS_STATUS ads_rc;
3097         ADS_STRUCT *ads = NULL;
3098         NT_PRINTER_INFO_LEVEL *printer = NULL;
3099         WERROR win_rc;
3100
3101         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3102         if (!W_ERROR_IS_OK(win_rc))
3103                 goto done;
3104
3105         switch (action) {
3106         case SPOOL_DS_PUBLISH:
3107         case SPOOL_DS_UPDATE:
3108                 /* set the DsSpooler info and attributes */
3109                 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3110                         win_rc = WERR_NOMEM;
3111                         goto done;
3112                 }
3113
3114                 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3115                 break;
3116         case SPOOL_DS_UNPUBLISH:
3117                 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3118                 break;
3119         default:
3120                 win_rc = WERR_NOT_SUPPORTED;
3121                 goto done;
3122         }
3123
3124         win_rc = mod_a_printer(printer, 2);
3125         if (!W_ERROR_IS_OK(win_rc)) {
3126                 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3127                 goto done;
3128         }
3129
3130         ads = ads_init(NULL, NULL, NULL);
3131         if (!ads) {
3132                 DEBUG(3, ("ads_init() failed\n"));
3133                 win_rc = WERR_SERVER_UNAVAILABLE;
3134                 goto done;
3135         }
3136         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3137         SAFE_FREE(ads->auth.password);
3138         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3139                 NULL, NULL);
3140
3141         /* ads_connect() will find the DC for us */                                         
3142         ads_rc = ads_connect(ads);
3143         if (!ADS_ERR_OK(ads_rc)) {
3144                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3145                 win_rc = WERR_ACCESS_DENIED;
3146                 goto done;
3147         }
3148
3149         switch (action) {
3150         case SPOOL_DS_PUBLISH:
3151         case SPOOL_DS_UPDATE:
3152                 win_rc = nt_printer_publish_ads(ads, printer);
3153                 break;
3154         case SPOOL_DS_UNPUBLISH:
3155                 win_rc = nt_printer_unpublish_ads(ads, printer);
3156                 break;
3157         }
3158
3159 done:
3160         free_a_printer(&printer, 2);
3161         ads_destroy(&ads);
3162         return win_rc;
3163 }
3164
3165 WERROR check_published_printers(void)
3166 {
3167         ADS_STATUS ads_rc;
3168         ADS_STRUCT *ads = NULL;
3169         int snum;
3170         int n_services = lp_numservices();
3171         NT_PRINTER_INFO_LEVEL *printer = NULL;
3172
3173         ads = ads_init(NULL, NULL, NULL);
3174         if (!ads) {
3175                 DEBUG(3, ("ads_init() failed\n"));
3176                 return WERR_SERVER_UNAVAILABLE;
3177         }
3178         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3179         SAFE_FREE(ads->auth.password);
3180         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3181                 NULL, NULL);
3182
3183         /* ads_connect() will find the DC for us */                                         
3184         ads_rc = ads_connect(ads);
3185         if (!ADS_ERR_OK(ads_rc)) {
3186                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3187                 ads_destroy(&ads);
3188                 return WERR_ACCESS_DENIED;
3189         }
3190
3191         for (snum = 0; snum < n_services; snum++) {
3192                 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3193                         continue;
3194
3195                 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3196                                                 lp_servicename(snum))) &&
3197                     (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3198                         nt_printer_publish_ads(ads, printer);
3199
3200                 free_a_printer(&printer, 2);
3201         }
3202
3203         ads_destroy(&ads);
3204         return WERR_OK;
3205 }
3206
3207 BOOL is_printer_published(Printer_entry *print_hnd, int snum, 
3208                           struct uuid *guid)
3209 {
3210         NT_PRINTER_INFO_LEVEL *printer = NULL;
3211         REGVAL_CTR *ctr;
3212         REGISTRY_VALUE *guid_val;
3213         WERROR win_rc;
3214         int i;
3215
3216         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3217
3218         if (!W_ERROR_IS_OK(win_rc) ||
3219             !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3220             ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3221             !(ctr = printer->info_2->data->keys[i].values) ||
3222             !(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) 
3223         {
3224                 free_a_printer(&printer, 2);
3225                 return False;
3226         }
3227
3228         /* fetching printer guids really ought to be a separate function.. */
3229         if (guid && regval_size(guid_val) == sizeof(struct uuid))
3230                 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
3231
3232         free_a_printer(&printer, 2);
3233         return True;
3234 }
3235 #else
3236 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3237 {
3238         return WERR_OK;
3239 }
3240
3241 WERROR check_published_printers(void)
3242 {
3243         return WERR_OK;
3244 }
3245
3246 BOOL is_printer_published(Printer_entry *print_hnd, int snum, 
3247                           struct uuid *guid)
3248 {
3249         return False;
3250 }
3251 #endif /* HAVE_ADS */
3252
3253 /****************************************************************************
3254  ***************************************************************************/
3255  
3256 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3257 {
3258         NT_PRINTER_DATA *data;
3259         int             i;
3260         int             removed_keys = 0;
3261         int             empty_slot;
3262         
3263         data = p2->data;
3264         empty_slot = data->num_keys;
3265
3266         if ( !key )
3267                 return WERR_INVALID_PARAM;
3268         
3269         /* remove all keys */
3270
3271         if ( !strlen(key) ) {
3272         
3273                 TALLOC_FREE( data );
3274
3275                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3276                         p2->printername ));
3277         
3278                 return WERR_OK;
3279         }
3280
3281         /* remove a specific key (and all subkeys) */
3282         
3283         for ( i=0; i<data->num_keys; i++ ) {
3284                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3285                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3286                                 data->keys[i].name));
3287                 
3288                         TALLOC_FREE( data->keys[i].name );
3289                         TALLOC_FREE( data->keys[i].values );
3290
3291                         /* mark the slot as empty */
3292
3293                         ZERO_STRUCTP( &data->keys[i] );
3294                 }
3295         }
3296
3297         /* find the first empty slot */
3298
3299         for ( i=0; i<data->num_keys; i++ ) {
3300                 if ( !data->keys[i].name ) {
3301                         empty_slot = i;
3302                         removed_keys++;
3303                         break;
3304                 }
3305         }
3306
3307         if ( i == data->num_keys )
3308                 /* nothing was removed */
3309                 return WERR_INVALID_PARAM;
3310
3311         /* move everything down */
3312         
3313         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3314                 if ( data->keys[i].name ) {
3315                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) ); 
3316                         ZERO_STRUCTP( &data->keys[i] );
3317                         empty_slot++;
3318                         removed_keys++;
3319                 }
3320         }
3321
3322         /* update count */
3323                 
3324         data->num_keys -= removed_keys;
3325
3326         /* sanity check to see if anything is left */
3327
3328         if ( !data->num_keys ) {
3329                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3330
3331                 SAFE_FREE( data->keys );
3332                 ZERO_STRUCTP( data );
3333         }
3334
3335         return WERR_OK;
3336 }
3337
3338 /****************************************************************************
3339  ***************************************************************************/
3340  
3341 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3342 {
3343         WERROR          result = WERR_OK;
3344         int             key_index;
3345         
3346         /* we must have names on non-zero length */
3347         
3348         if ( !key || !*key|| !value || !*value )
3349                 return WERR_INVALID_NAME;
3350                 
3351         /* find the printer key first */
3352
3353         key_index = lookup_printerkey( p2->data, key );
3354         if ( key_index == -1 )
3355                 return WERR_OK;
3356         
3357         /* make sure the value exists so we can return the correct error code */
3358         
3359         if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3360                 return WERR_BADFILE;
3361                 
3362         regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3363         
3364         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3365                 key, value ));
3366         
3367         return result;
3368 }
3369
3370 /****************************************************************************
3371  ***************************************************************************/
3372  
3373 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value, 
3374                            uint32 type, uint8 *data, int real_len )
3375 {
3376         WERROR          result = WERR_OK;
3377         int             key_index;
3378
3379         /* we must have names on non-zero length */
3380         
3381         if ( !key || !*key|| !value || !*value )
3382                 return WERR_INVALID_NAME;
3383                 
3384         /* find the printer key first */
3385         
3386         key_index = lookup_printerkey( p2->data, key );
3387         if ( key_index == -1 )
3388                 key_index = add_new_printer_key( p2->data, key );
3389                 
3390         if ( key_index == -1 )
3391                 return WERR_NOMEM;
3392         
3393         regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3394                 type, (const char *)data, real_len );
3395         
3396         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3397                 key, value, type, real_len  ));
3398         
3399         return result;
3400 }
3401
3402 /****************************************************************************
3403  ***************************************************************************/
3404  
3405 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3406 {
3407         int             key_index;
3408
3409         if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3410                 return NULL;
3411
3412         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3413                 key, value ));
3414
3415         return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3416 }
3417
3418 /****************************************************************************
3419  Unpack a list of registry values frem the TDB
3420  ***************************************************************************/
3421  
3422 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3423 {
3424         int             len = 0;
3425         uint32          type;
3426         pstring         string, valuename, keyname;
3427         char            *str;
3428         int             size;
3429         uint8           *data_p;
3430         REGISTRY_VALUE  *regval_p;
3431         int             key_index;
3432
3433         /* add the "PrinterDriverData" key first for performance reasons */
3434         
3435         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3436
3437         /* loop and unpack the rest of the registry values */
3438         
3439         while ( True ) {
3440         
3441                 /* check to see if there are any more registry values */
3442                 
3443                 regval_p = NULL;
3444                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);         
3445                 if ( !regval_p ) 
3446                         break;
3447
3448                 /* unpack the next regval */
3449                 
3450                 len += tdb_unpack(buf+len, buflen-len, "fdB",
3451                                   string,
3452                                   &type,
3453                                   &size,
3454                                   &data_p);
3455
3456                 /* lookup for subkey names which have a type of REG_NONE */
3457                 /* there's no data with this entry */
3458
3459                 if ( type == REG_NONE ) {
3460                         if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3461                                 add_new_printer_key( printer_data, string );
3462                         continue;
3463                 }
3464         
3465                 /*
3466                  * break of the keyname from the value name.  
3467                  * Valuenames can have embedded '\'s so be careful.
3468                  * only support one level of keys.  See the 
3469                  * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3470                  * -- jerry
3471                  */     
3472                  
3473                 str = strchr_m( string, '\\');
3474                 
3475                 /* Put in "PrinterDriverData" is no key specified */
3476                 
3477                 if ( !str ) {
3478                         pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3479                         pstrcpy( valuename, string );
3480                 }
3481                 else {
3482                         *str = '\0';
3483                         pstrcpy( keyname, string );
3484                         pstrcpy( valuename, str+1 );
3485                 }
3486                         
3487                 /* see if we need a new key */
3488                 
3489                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3490                         key_index = add_new_printer_key( printer_data, keyname );
3491                         
3492                 if ( key_index == -1 ) {
3493                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3494                                 keyname));
3495                         break;
3496                 }
3497                 
3498                 /* add the new value */
3499                 
3500                 regval_ctr_addvalue( printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3501
3502                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3503
3504                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3505         }
3506
3507         return len;
3508 }
3509
3510 /****************************************************************************
3511  ***************************************************************************/
3512
3513 static void map_to_os2_driver(fstring drivername)
3514 {
3515         static BOOL initialised=False;
3516         static fstring last_from,last_to;
3517         char *mapfile = lp_os2_driver_map();
3518         char **lines = NULL;
3519         int numlines = 0;
3520         int i;
3521
3522         if (!strlen(drivername))
3523                 return;
3524
3525         if (!*mapfile)
3526                 return;
3527
3528         if (!initialised) {
3529                 *last_from = *last_to = 0;
3530                 initialised = True;
3531         }
3532
3533         if (strequal(drivername,last_from)) {
3534                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3535                 fstrcpy(drivername,last_to);
3536                 return;
3537         }
3538
3539         lines = file_lines_load(mapfile, &numlines);
3540         if (numlines == 0) {
3541                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3542                 return;
3543         }
3544
3545         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3546
3547         for( i = 0; i < numlines; i++) {
3548                 char *nt_name = lines[i];
3549                 char *os2_name = strchr(nt_name,'=');
3550
3551                 if (!os2_name)
3552                         continue;
3553
3554                 *os2_name++ = 0;
3555
3556                 while (isspace(*nt_name))
3557                         nt_name++;
3558
3559                 if (!*nt_name || strchr("#;",*nt_name))
3560                         continue;
3561
3562                 {
3563                         int l = strlen(nt_name);
3564                         while (l && isspace(nt_name[l-1])) {
3565                                 nt_name[l-1] = 0;
3566                                 l--;
3567                         }
3568                 }
3569
3570                 while (isspace(*os2_name))
3571                         os2_name++;
3572
3573                 {
3574                         int l = strlen(os2_name);
3575                         while (l && isspace(os2_name[l-1])) {
3576                                 os2_name[l-1] = 0;
3577                                 l--;
3578                         }
3579                 }
3580
3581                 if (strequal(nt_name,drivername)) {
3582                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3583                         fstrcpy(last_from,drivername);
3584                         fstrcpy(last_to,os2_name);
3585                         fstrcpy(drivername,os2_name);
3586                         file_lines_free(lines);
3587                         return;
3588                 }
3589         }
3590
3591         file_lines_free(lines);
3592 }
3593
3594 /****************************************************************************
3595  Get a default printer info 2 struct.
3596 ****************************************************************************/
3597 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
3598 {
3599         int snum;
3600
3601         snum = lp_servicenumber(sharename);
3602
3603         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3604         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s", 
3605                 servername, sharename);
3606         fstrcpy(info->sharename, sharename);
3607         fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3608
3609         /* by setting the driver name to an empty string, a local NT admin
3610            can now run the **local** APW to install a local printer driver
3611            for a Samba shared printer in 2.2.  Without this, drivers **must** be 
3612            installed on the Samba server for NT clients --jerry */
3613 #if 0   /* JERRY --do not uncomment-- */
3614         if (!*info->drivername)
3615                 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3616 #endif
3617
3618
3619         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3620
3621         pstrcpy(info->comment, "");
3622         fstrcpy(info->printprocessor, "winprint");
3623         fstrcpy(info->datatype, "RAW");
3624
3625         info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3626
3627         info->starttime = 0; /* Minutes since 12:00am GMT */
3628         info->untiltime = 0; /* Minutes since 12:00am GMT */
3629         info->priority = 1;
3630         info->default_priority = 1;
3631         info->setuptime = (uint32)time(NULL);
3632
3633         /*
3634          * I changed this as I think it is better to have a generic
3635          * DEVMODE than to crash Win2k explorer.exe   --jerry
3636          * See the HP Deskjet 990c Win2k drivers for an example.
3637          *
3638          * However the default devmode appears to cause problems
3639          * with the HP CLJ 8500 PCL driver.  Hence the addition of
3640          * the "default devmode" parameter   --jerry 22/01/2002
3641          */
3642
3643         if (lp_default_devmode(snum)) {
3644                 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL)
3645                         goto fail;
3646         }
3647         else {
3648                 info->devmode = NULL;
3649         }
3650
3651         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf))
3652                 goto fail;
3653
3654         return WERR_OK;
3655
3656 fail:
3657         if (info->devmode)
3658                 free_nt_devicemode(&info->devmode);
3659
3660         return WERR_ACCESS_DENIED;
3661 }
3662
3663 /****************************************************************************
3664 ****************************************************************************/
3665 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
3666 {
3667         int len = 0;
3668         int snum = lp_servicenumber(sharename);
3669         TDB_DATA kbuf, dbuf;
3670         fstring printername;
3671         char adevice[MAXDEVICENAME];
3672                 
3673         kbuf = make_printer_tdbkey( sharename );
3674
3675         dbuf = tdb_fetch(tdb_printers, kbuf);
3676         if (!dbuf.dptr)
3677                 return get_a_printer_2_default(info, servername, sharename);
3678
3679         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3680                         &info->attributes,
3681                         &info->priority,
3682                         &info->default_priority,
3683                         &info->starttime,
3684                         &info->untiltime,
3685                         &info->status,
3686                         &info->cjobs,
3687                         &info->averageppm,
3688                         &info->changeid,
3689                         &info->c_setprinter,
3690                         &info->setuptime,
3691                         info->servername,
3692                         info->printername,
3693                         info->sharename,
3694                         info->portname,
3695                         info->drivername,
3696                         info->comment,
3697                         info->location,
3698                         info->sepfile,
3699                         info->printprocessor,
3700                         info->datatype,
3701                         info->parameters);
3702
3703         /* Samba has to have shared raw drivers. */
3704         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3705         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3706
3707         /* Restore the stripped strings. */
3708         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3709
3710         if ( lp_force_printername(snum) )
3711                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3712         else 
3713                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3714
3715         fstrcpy(info->printername, printername);
3716
3717         len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
3718
3719         /*
3720          * Some client drivers freak out if there is a NULL devmode
3721          * (probably the driver is not checking before accessing 
3722          * the devmode pointer)   --jerry
3723          *
3724          * See comments in get_a_printer_2_default()
3725          */
3726
3727         if (lp_default_devmode(snum) && !info->devmode) {
3728                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3729                         printername));
3730                 info->devmode = construct_nt_devicemode(printername);
3731         }
3732
3733         slprintf( adevice, sizeof(adevice), "%s", info->printername );
3734         if (info->devmode) {
3735                 fstrcpy(info->devmode->devicename, adevice);    
3736         }
3737
3738         if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
3739                 DEBUG(0,("unpack_values: talloc() failed!\n"));
3740                 return WERR_NOMEM;
3741         }
3742         len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
3743
3744         /* This will get the current RPC talloc context, but we should be
3745            passing this as a parameter... fixme... JRA ! */
3746
3747         nt_printing_getsec(info, sharename, &info->secdesc_buf);
3748
3749         /* Fix for OS/2 drivers. */
3750
3751         if (get_remote_arch() == RA_OS2)
3752                 map_to_os2_driver(info->drivername);
3753
3754         SAFE_FREE(dbuf.dptr);
3755
3756         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3757                  sharename, info->printername, info->drivername));
3758
3759         return WERR_OK; 
3760 }
3761
3762 /****************************************************************************
3763  Debugging function, dump at level 6 the struct in the logs.
3764 ****************************************************************************/
3765 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3766 {
3767         uint32 result;
3768         NT_PRINTER_INFO_LEVEL_2 *info2;
3769         
3770         DEBUG(106,("Dumping printer at level [%d]\n", level));
3771         
3772         switch (level) {
3773                 case 2:
3774                 {
3775                         if (printer->info_2 == NULL)
3776                                 result=5;
3777                         else
3778                         {
3779                                 info2=printer->info_2;
3780                         
3781                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3782                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3783                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3784                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3785                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3786                                 DEBUGADD(106,("status:[%d]\n", info2->status));
3787                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3788                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3789                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3790                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3791                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3792
3793                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3794                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3795                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3796                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3797                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3798                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3799                                 DEBUGADD(106,("location:[%s]\n", info2->location));
3800                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3801                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3802                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3803                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3804                                 result=0;
3805                         }
3806                         break;
3807                 }
3808                 default:
3809                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3810                         result=1;
3811                         break;
3812         }
3813         
3814         return result;
3815 }
3816
3817 /****************************************************************************
3818  Update the changeid time.
3819  This is SO NASTY as some drivers need this to change, others need it
3820  static. This value will change every second, and I must hope that this
3821  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3822  UTAH ! JRA.
3823 ****************************************************************************/
3824
3825 static uint32 rev_changeid(void)
3826 {
3827         struct timeval tv;
3828
3829         get_process_uptime(&tv);
3830
3831 #if 1   /* JERRY */
3832         /* Return changeid as msec since spooler restart */
3833         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3834 #else
3835         /*
3836          * This setting seems to work well but is too untested
3837          * to replace the above calculation.  Left in for experiementation
3838          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
3839          */
3840         return tv.tv_sec * 10 + tv.tv_usec / 100000;
3841 #endif
3842 }
3843
3844
3845 /*
3846  * The function below are the high level ones.
3847  * only those ones must be called from the spoolss code.
3848  * JFM.
3849  */
3850
3851 /****************************************************************************
3852  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3853 ****************************************************************************/
3854
3855 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3856 {
3857         WERROR result;
3858         
3859         dump_a_printer(printer, level); 
3860         
3861         switch (level) {
3862                 case 2:
3863                 {
3864                         /*
3865                          * Update the changestamp.  Emperical tests show that the
3866                          * ChangeID is always updated,but c_setprinter is  
3867                          *  global spooler variable (not per printer).
3868                          */
3869
3870                         /* ChangeID **must** be increasing over the lifetime
3871                            of client's spoolss service in order for the
3872                            client's cache to show updates */
3873
3874                         printer->info_2->changeid = rev_changeid();
3875
3876                         /*
3877                          * Because one day someone will ask:
3878                          * NT->NT       An admin connection to a remote
3879                          *              printer show changes imeediately in
3880                          *              the properities dialog
3881                          *      
3882                          *              A non-admin connection will only show the
3883                          *              changes after viewing the properites page
3884                          *              2 times.  Seems to be related to a
3885                          *              race condition in the client between the spooler
3886                          *              updating the local cache and the Explorer.exe GUI
3887                          *              actually displaying the properties.
3888                          *
3889                          *              This is fixed in Win2k.  admin/non-admin
3890                          *              connections both display changes immediately.
3891                          *
3892                          * 14/12/01     --jerry
3893                          */
3894
3895                         result=update_a_printer_2(printer->info_2);
3896                         
3897                         break;
3898                 }
3899                 default:
3900                         result=WERR_UNKNOWN_LEVEL;
3901                         break;
3902         }
3903         
3904         return result;
3905 }
3906
3907 /****************************************************************************
3908  Initialize printer devmode & data with previously saved driver init values.
3909 ****************************************************************************/
3910
3911 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3912 {
3913         int                     len = 0;
3914         pstring                 key;
3915         TDB_DATA                kbuf, dbuf;
3916         NT_PRINTER_INFO_LEVEL_2 info;
3917
3918
3919         ZERO_STRUCT(info);
3920
3921         /*
3922          * Delete any printer data 'values' already set. When called for driver
3923          * replace, there will generally be some, but during an add printer, there
3924          * should not be any (if there are delete them).
3925          */
3926          
3927         if ( info_ptr->data )
3928                 delete_all_printer_data( info_ptr, "" );
3929         
3930         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3931
3932         kbuf.dptr = key;
3933         kbuf.dsize = strlen(key)+1;
3934
3935         dbuf = tdb_fetch(tdb_drivers, kbuf);
3936         if (!dbuf.dptr) {
3937                 /*
3938                  * When changing to a driver that has no init info in the tdb, remove
3939                  * the previous drivers init info and leave the new on blank.
3940                  */
3941                 free_nt_devicemode(&info_ptr->devmode);
3942                 return False;
3943         }
3944         
3945         /*
3946          * Get the saved DEVMODE..
3947          */
3948          
3949         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3950
3951         /*
3952          * The saved DEVMODE contains the devicename from the printer used during
3953          * the initialization save. Change it to reflect the new printer.
3954          */
3955          
3956         if ( info.devmode ) {
3957                 ZERO_STRUCT(info.devmode->devicename);
3958                 fstrcpy(info.devmode->devicename, info_ptr->printername);
3959         }
3960
3961         /*
3962          * NT/2k does not change out the entire DeviceMode of a printer
3963          * when changing the driver.  Only the driverextra, private, & 
3964          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
3965          *
3966          * Later examination revealed that Windows NT/2k does reset the
3967          * the printer's device mode, bit **only** when you change a 
3968          * property of the device mode such as the page orientation.
3969          * --jerry
3970          */
3971
3972
3973         /* Bind the saved DEVMODE to the new the printer */
3974          
3975         free_nt_devicemode(&info_ptr->devmode);
3976         info_ptr->devmode = info.devmode;
3977
3978         DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3979                 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3980
3981         /* Add the printer data 'values' to the new printer */
3982
3983         if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
3984                 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
3985                 return False;
3986         }
3987          
3988         len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3989         
3990
3991         SAFE_FREE(dbuf.dptr);
3992
3993         return True;    
3994 }
3995
3996 /****************************************************************************
3997  Initialize printer devmode & data with previously saved driver init values.
3998  When a printer is created using AddPrinter, the drivername bound to the
3999  printer is used to lookup previously saved driver initialization info, which
4000  is bound to the new printer.
4001 ****************************************************************************/
4002
4003 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4004 {
4005         BOOL result = False;
4006         
4007         switch (level) {
4008                 case 2:
4009                         result = set_driver_init_2(printer->info_2);
4010                         break;
4011                         
4012                 default:
4013                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
4014                                 level));
4015                         break;
4016         }
4017         
4018         return result;
4019 }
4020
4021 /****************************************************************************
4022  Delete driver init data stored for a specified driver
4023 ****************************************************************************/
4024
4025 BOOL del_driver_init(char *drivername)
4026 {
4027         pstring key;
4028         TDB_DATA kbuf;
4029
4030         if (!drivername || !*drivername) {
4031                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4032                 return False;
4033         }
4034
4035         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
4036
4037         kbuf.dptr = key;
4038         kbuf.dsize = strlen(key)+1;
4039
4040         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
4041
4042         return (tdb_delete(tdb_drivers, kbuf) == 0);
4043 }
4044
4045 /****************************************************************************
4046  Pack up the DEVMODE and values for a printer into a 'driver init' entry 
4047  in the tdb. Note: this is different from the driver entry and the printer
4048  entry. There should be a single driver init entry for each driver regardless
4049  of whether it was installed from NT or 2K. Technically, they should be
4050  different, but they work out to the same struct.
4051 ****************************************************************************/
4052
4053 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4054 {
4055         pstring key;
4056         char *buf;
4057         int buflen, len, ret;
4058         TDB_DATA kbuf, dbuf;
4059
4060         buf = NULL;
4061         buflen = 0;
4062
4063  again: 
4064         len = 0;
4065         len += pack_devicemode(info->devmode, buf+len, buflen-len);
4066
4067         len += pack_values( info->data, buf+len, buflen-len );
4068
4069         if (buflen < len) {
4070                 char *tb;
4071
4072                 tb = (char *)SMB_REALLOC(buf, len);
4073                 if (!tb) {
4074                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4075                         ret = -1;
4076                         goto done;
4077                 }
4078                 else
4079                         buf = tb;
4080                 buflen = len;
4081                 goto again;
4082         }
4083
4084         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4085
4086         kbuf.dptr = key;
4087         kbuf.dsize = strlen(key)+1;
4088         dbuf.dptr = buf;
4089         dbuf.dsize = len;
4090
4091         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
4092
4093 done:
4094         if (ret == -1)
4095                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4096
4097         SAFE_FREE(buf);
4098
4099         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4100                  info->sharename, info->drivername));
4101
4102         return ret;
4103 }
4104
4105 /****************************************************************************
4106  Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4107 ****************************************************************************/
4108
4109 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4110 {
4111         uint32 result;
4112         
4113         dump_a_printer(printer, level); 
4114         
4115         switch (level) {
4116                 case 2:
4117                         result = update_driver_init_2(printer->info_2);
4118                         break;
4119                 default:
4120                         result = 1;
4121                         break;
4122         }
4123         
4124         return result;
4125 }
4126
4127 /****************************************************************************
4128  Convert the printer data value, a REG_BINARY array, into an initialization 
4129  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4130  got to keep the endians happy :).
4131 ****************************************************************************/
4132
4133 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4134 {
4135         BOOL       result = False;
4136         prs_struct ps;
4137         DEVICEMODE devmode;
4138
4139         ZERO_STRUCT(devmode);
4140
4141         prs_init(&ps, 0, ctx, UNMARSHALL);
4142         ps.data_p      = (char *)data;
4143         ps.buffer_size = data_len;
4144
4145         if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4146                 result = convert_devicemode("", &devmode, &nt_devmode);
4147         else
4148                 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4149
4150         return result;
4151 }
4152
4153 /****************************************************************************
4154  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4155
4156  1. Use the driver's config DLL to this UNC printername and:
4157     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4158     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4159  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4160
4161  The last step triggers saving the "driver initialization" information for
4162  this printer into the tdb. Later, new printers that use this driver will
4163  have this initialization information bound to them. This simulates the
4164  driver initialization, as if it had run on the Samba server (as it would
4165  have done on NT).
4166
4167  The Win32 client side code requirement sucks! But until we can run arbitrary
4168  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4169  
4170  It would have been easier to use SetPrinter because all the UNMARSHALLING of
4171  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4172  about it and you will realize why.  JRR 010720
4173 ****************************************************************************/
4174
4175 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4176 {
4177         WERROR        status       = WERR_OK;
4178         TALLOC_CTX    *ctx         = NULL;
4179         NT_DEVICEMODE *nt_devmode  = NULL;
4180         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4181         
4182         /*
4183          * When the DEVMODE is already set on the printer, don't try to unpack it.
4184          */
4185         DEBUG(8,("save_driver_init_2: Enter...\n"));
4186         
4187         if ( !printer->info_2->devmode && data_len ) {
4188                 /*
4189                  * Set devmode on printer info, so entire printer initialization can be
4190                  * saved to tdb.
4191                  */
4192
4193                 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4194                         return WERR_NOMEM;
4195
4196                 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4197                         status = WERR_NOMEM;
4198                         goto done;
4199                 }
4200         
4201                 ZERO_STRUCTP(nt_devmode);
4202
4203                 /*
4204                  * The DEVMODE is held in the 'data' component of the param in raw binary.
4205                  * Convert it to to a devmode structure
4206                  */
4207                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4208                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4209                         status = WERR_INVALID_PARAM;
4210                         goto done;
4211                 }
4212
4213                 printer->info_2->devmode = nt_devmode;
4214         }
4215
4216         /*
4217          * Pack up and add (or update) the DEVMODE and any current printer data to
4218          * a 'driver init' element in the tdb
4219          * 
4220          */
4221
4222         if ( update_driver_init(printer, 2) != 0 ) {
4223                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4224                 status = WERR_NOMEM;
4225                 goto done;
4226         }
4227         
4228         /*
4229          * If driver initialization info was successfully saved, set the current 
4230          * printer to match it. This allows initialization of the current printer 
4231          * as well as the driver.
4232          */
4233         status = mod_a_printer(printer, 2);
4234         if (!W_ERROR_IS_OK(status)) {
4235                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4236                                   printer->info_2->printername));
4237         }
4238         
4239   done:
4240         talloc_destroy(ctx);
4241         free_nt_devicemode( &nt_devmode );
4242         
4243         printer->info_2->devmode = tmp_devmode;
4244
4245         return status;
4246 }
4247
4248 /****************************************************************************
4249  Update the driver init info (DEVMODE and specifics) for a printer
4250 ****************************************************************************/
4251
4252 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4253 {
4254         WERROR status = WERR_OK;
4255         
4256         switch (level) {
4257                 case 2:
4258                         status = save_driver_init_2( printer, data, data_len );
4259                         break;
4260                 default:
4261                         status = WERR_UNKNOWN_LEVEL;
4262                         break;
4263         }
4264         
4265         return status;
4266 }
4267
4268 /****************************************************************************
4269  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4270
4271  Previously the code had a memory allocation problem because it always
4272  used the TALLOC_CTX from the Printer_entry*.   This context lasts 
4273  as a long as the original handle is open.  So if the client made a lot 
4274  of getprinter[data]() calls, the memory usage would climb.  Now we use
4275  a short lived TALLOC_CTX for printer_info_2 objects returned.  We 
4276  still use the Printer_entry->ctx for maintaining the cache copy though
4277  since that object must live as long as the handle by definition.  
4278                                                     --jerry
4279
4280 ****************************************************************************/
4281
4282 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, 
4283                         const char *sharename)
4284 {
4285         WERROR result;
4286         fstring servername;
4287         
4288         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4289
4290         if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4291                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4292                 return WERR_NOMEM;
4293         }
4294
4295         switch (level) {
4296                 case 2:
4297                         if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4298                                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4299                                 TALLOC_FREE( *pp_printer );
4300                                 return WERR_NOMEM;
4301                         }
4302
4303                         if ( print_hnd ) 
4304                                 fstrcpy( servername, print_hnd->servername );
4305                         else {
4306                                 fstrcpy( servername, "%L" );
4307                                 standard_sub_basic( "", servername, sizeof(servername)-1 );
4308                         }
4309
4310                         result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4311         
4312                         
4313                         /* we have a new printer now.  Save it with this handle */
4314                         
4315                         if ( !W_ERROR_IS_OK(result) ) {
4316                                 TALLOC_FREE( *pp_printer );
4317                                 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", 
4318                                         sharename, (unsigned int)level, dos_errstr(result)));
4319                                 return result;
4320                         }
4321
4322                         dump_a_printer( *pp_printer, level);
4323                         
4324                         break;
4325                         
4326                 default:
4327                         TALLOC_FREE( *pp_printer );
4328                         return WERR_UNKNOWN_LEVEL;
4329         }
4330         
4331         return WERR_OK;
4332 }
4333
4334 /****************************************************************************
4335  Deletes a NT_PRINTER_INFO_LEVEL struct.
4336 ****************************************************************************/
4337
4338 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4339 {
4340         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4341
4342         if ( !printer )
4343                 return 0;
4344         
4345         switch (level) {
4346                 case 2:
4347                         if ( printer->info_2 ) 
4348                                 free_nt_printer_info_level_2(&printer->info_2);
4349                         break;
4350
4351                 default:
4352                         DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4353                         return 1;
4354         }
4355
4356         TALLOC_FREE(*pp_printer);
4357
4358         return 0;
4359 }
4360
4361 /****************************************************************************
4362 ****************************************************************************/
4363 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4364 {
4365         uint32 result;
4366         DEBUG(104,("adding a printer at level [%d]\n", level));
4367         dump_a_printer_driver(driver, level);
4368         
4369         switch (level) {
4370                 case 3:
4371                         result=add_a_printer_driver_3(driver.info_3);
4372                         break;
4373
4374                 case 6:
4375                         result=add_a_printer_driver_6(driver.info_6);
4376                         break;
4377
4378                 default:
4379                         result=1;
4380                         break;
4381         }
4382         
4383         return result;
4384 }
4385 /****************************************************************************
4386 ****************************************************************************/
4387
4388 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4389                             fstring drivername, const char *architecture, uint32 version)
4390 {
4391         WERROR result;
4392         
4393         switch (level) {
4394                 case 3:
4395                         /* Sometime we just want any version of the driver */
4396                         
4397                         if ( version == DRIVER_ANY_VERSION ) {
4398                                 /* look for Win2k first and then for NT4 */
4399                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4400                                                 architecture, 3);
4401                                                 
4402                                 if ( !W_ERROR_IS_OK(result) ) {
4403                                         result = get_a_printer_driver_3( &driver->info_3, 
4404                                                         drivername, architecture, 2 );
4405                                 }
4406                         } else {
4407                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4408                                         architecture, version);                         
4409                         }
4410                         break;
4411                         
4412                 default:
4413                         result=W_ERROR(1);
4414                         break;
4415         }
4416         
4417         if (W_ERROR_IS_OK(result))
4418                 dump_a_printer_driver(*driver, level);
4419                 
4420         return result;
4421 }
4422
4423 /****************************************************************************
4424 ****************************************************************************/
4425 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4426 {
4427         uint32 result;
4428         
4429         switch (level) {
4430                 case 3:
4431                 {
4432                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4433                         if (driver.info_3 != NULL)
4434                         {
4435                                 info3=driver.info_3;
4436                                 SAFE_FREE(info3->dependentfiles);
4437                                 ZERO_STRUCTP(info3);
4438                                 SAFE_FREE(info3);
4439                                 result=0;
4440                         } else {
4441                                 result=4;
4442                         }
4443                         break;
4444                 }
4445                 case 6:
4446                 {
4447                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4448                         if (driver.info_6 != NULL) {
4449                                 info6=driver.info_6;
4450                                 SAFE_FREE(info6->dependentfiles);
4451                                 SAFE_FREE(info6->previousnames);
4452                                 ZERO_STRUCTP(info6);
4453                                 SAFE_FREE(info6);
4454                                 result=0;
4455                         } else {
4456                                 result=4;
4457                         }
4458                         break;
4459                 }
4460                 default:
4461                         result=1;
4462                         break;
4463         }
4464         return result;
4465 }
4466
4467
4468 /****************************************************************************
4469   Determine whether or not a particular driver is currently assigned
4470   to a printer
4471 ****************************************************************************/
4472
4473 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4474 {
4475         int snum;
4476         int n_services = lp_numservices();
4477         NT_PRINTER_INFO_LEVEL *printer = NULL;
4478         BOOL in_use = False;
4479
4480         if ( !info_3 ) 
4481                 return False;
4482
4483         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4484         
4485         /* loop through the printers.tdb and check for the drivername */
4486         
4487         for (snum=0; snum<n_services && !in_use; snum++) {
4488                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4489                         continue;
4490                 
4491                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4492                         continue;
4493                 
4494                 if ( strequal(info_3->name, printer->info_2->drivername) ) 
4495                         in_use = True;
4496                 
4497                 free_a_printer( &printer, 2 );
4498         }
4499         
4500         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4501         
4502         if ( in_use ) {
4503                 NT_PRINTER_DRIVER_INFO_LEVEL d;
4504                 WERROR werr;
4505                 
4506                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4507                 
4508                 /* we can still remove the driver if there is one of 
4509                    "Windows NT x86" version 2 or 3 left */
4510                    
4511                 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4512                         werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );                       
4513                 }
4514                 else {
4515                         switch ( info_3->cversion ) {
4516                         case 2:
4517                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4518                                 break;
4519                         case 3: 
4520                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4521                                 break;
4522                         default:
4523                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n", 
4524                                         info_3->cversion));
4525                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4526                                 break;
4527                         }
4528                 }
4529
4530                 /* now check the error code */
4531                                 
4532                 if ( W_ERROR_IS_OK(werr) ) {
4533                         /* it's ok to remove the driver, we have other architctures left */
4534                         in_use = False;
4535                         free_a_printer_driver( d, 3 );
4536                 }
4537         }
4538         
4539         /* report that the driver is not in use by default */
4540         
4541         return in_use;
4542 }
4543
4544
4545 /**********************************************************************
4546  Check to see if a ogiven file is in use by *info
4547  *********************************************************************/
4548  
4549 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4550 {
4551         int i = 0;
4552         
4553         if ( !info )
4554                 return False;
4555                 
4556         if ( strequal(file, info->driverpath) )
4557                 return True;
4558
4559         if ( strequal(file, info->datafile) )
4560                 return True;
4561
4562         if ( strequal(file, info->configfile) )
4563                 return True;
4564
4565         if ( strequal(file, info->helpfile) )
4566                 return True;
4567         
4568         /* see of there are any dependent files to examine */
4569         
4570         if ( !info->dependentfiles )
4571                 return False;
4572         
4573         while ( *info->dependentfiles[i] ) {
4574                 if ( strequal(file, info->dependentfiles[i]) )
4575                         return True;
4576                 i++;
4577         }
4578         
4579         return False;
4580
4581 }
4582
4583 /**********************************************************************
4584  Utility function to remove the dependent file pointed to by the 
4585  input parameter from the list 
4586  *********************************************************************/
4587
4588 static void trim_dependent_file( fstring files[], int idx )
4589 {
4590         
4591         /* bump everything down a slot */
4592
4593         while( *files[idx+1] ) {
4594                 fstrcpy( files[idx], files[idx+1] );
4595                 idx++;
4596         }
4597         
4598         *files[idx] = '\0';
4599
4600         return; 
4601 }
4602
4603 /**********************************************************************
4604  Check if any of the files used by src are also used by drv 
4605  *********************************************************************/
4606
4607 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, 
4608                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4609 {
4610         BOOL    in_use = False;
4611         int     i = 0;
4612         
4613         if ( !src || !drv )
4614                 return False;
4615                 
4616         /* check each file.  Remove it from the src structure if it overlaps */
4617         
4618         if ( drv_file_in_use(src->driverpath, drv) ) {
4619                 in_use = True;
4620                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4621                 fstrcpy( src->driverpath, "" );
4622         }
4623                 
4624         if ( drv_file_in_use(src->datafile, drv) ) {
4625                 in_use = True;
4626                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4627                 fstrcpy( src->datafile, "" );
4628         }
4629                 
4630         if ( drv_file_in_use(src->configfile, drv) ) {
4631                 in_use = True;
4632                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4633                 fstrcpy( src->configfile, "" );
4634         }
4635                 
4636         if ( drv_file_in_use(src->helpfile, drv) ) {
4637                 in_use = True;
4638                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4639                 fstrcpy( src->helpfile, "" );
4640         }
4641         
4642         /* are there any dependentfiles to examine? */
4643         
4644         if ( !src->dependentfiles )
4645                 return in_use;
4646                 
4647         while ( *src->dependentfiles[i] ) {
4648                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4649                         in_use = True;
4650                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4651                         trim_dependent_file( src->dependentfiles, i );
4652                 } else
4653                         i++;
4654         }               
4655                 
4656         return in_use;
4657 }
4658
4659 /****************************************************************************
4660   Determine whether or not a particular driver files are currently being 
4661   used by any other driver.  
4662   
4663   Return value is True if any files were in use by other drivers
4664   and False otherwise.
4665   
4666   Upon return, *info has been modified to only contain the driver files
4667   which are not in use
4668 ****************************************************************************/
4669
4670 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4671 {
4672         int                             i;
4673         int                             ndrivers;
4674         uint32                          version;
4675         fstring                         *list = NULL;
4676         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
4677         
4678         if ( !info )
4679                 return False;
4680         
4681         version = info->cversion;
4682         
4683         /* loop over all driver versions */
4684         
4685         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4686         
4687         /* get the list of drivers */
4688                 
4689         list = NULL;
4690         ndrivers = get_ntdrivers(&list, info->environment, version);
4691                 
4692         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
4693                 ndrivers, info->environment, version));
4694
4695         /* check each driver for overlap in files */
4696                 
4697         for (i=0; i<ndrivers; i++) {
4698                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4699                         
4700                 ZERO_STRUCT(driver);
4701                         
4702                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4703                         SAFE_FREE(list);
4704                         return True;
4705                 }
4706                         
4707                 /* check if d2 uses any files from d1 */
4708                 /* only if this is a different driver than the one being deleted */
4709                         
4710                 if ( !strequal(info->name, driver.info_3->name) ) {
4711                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
4712                                 free_a_printer_driver(driver, 3);
4713                                 SAFE_FREE( list );
4714                                 return True;
4715                         }
4716                 }
4717         
4718                 free_a_printer_driver(driver, 3);
4719         }       
4720         
4721         SAFE_FREE(list);
4722         
4723         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4724         
4725         driver.info_3 = info;
4726         
4727         if ( DEBUGLEVEL >= 20 )
4728                 dump_a_printer_driver( driver, 3 );
4729         
4730         return False;
4731 }
4732
4733 /****************************************************************************
4734   Actually delete the driver files.  Make sure that 
4735   printer_driver_files_in_use() return False before calling 
4736   this.
4737 ****************************************************************************/
4738
4739 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4740 {
4741         int i = 0;
4742         char *s;
4743         pstring file;
4744         connection_struct *conn;
4745         DATA_BLOB null_pw;
4746         NTSTATUS nt_status;
4747         fstring res_type;
4748         BOOL bad_path;
4749         SMB_STRUCT_STAT  st;
4750
4751         if ( !info_3 )
4752                 return False;
4753                 
4754         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4755         
4756         /*
4757          * Connect to the print$ share under the same account as the 
4758          * user connected to the rpc pipe. Note we must be root to 
4759          * do this.
4760          */
4761          
4762         null_pw = data_blob( NULL, 0 );
4763         fstrcpy(res_type, "A:");
4764         become_root();
4765         conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4766         unbecome_root();
4767         
4768         if ( !conn ) {
4769                 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4770                 return False;
4771         }
4772
4773         /* Save who we are - we are temporarily becoming the connection user. */
4774
4775         if ( !become_user(conn, conn->vuid) ) {
4776                 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4777                 return False;
4778         }
4779
4780         /* now delete the files; must strip the '\print$' string from 
4781            fron of path                                                */
4782         
4783         if ( *info_3->driverpath ) {
4784                 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4785                         pstrcpy( file, s );
4786                         driver_unix_convert(file, conn, NULL, &bad_path, &st);
4787                         DEBUG(10,("deleting driverfile [%s]\n", s));
4788                         unlink_internals(conn, 0, file);
4789                 }
4790         }
4791                 
4792         if ( *info_3->configfile ) {
4793                 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4794                         pstrcpy( file, s );
4795                         driver_unix_convert(file, conn, NULL, &bad_path, &st);
4796                         DEBUG(10,("deleting configfile [%s]\n", s));
4797                         unlink_internals(conn, 0, file);
4798                 }
4799         }
4800         
4801         if ( *info_3->datafile ) {
4802                 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4803                         pstrcpy( file, s );
4804                         driver_unix_convert(file, conn, NULL, &bad_path, &st);
4805                         DEBUG(10,("deleting datafile [%s]\n", s));
4806                         unlink_internals(conn, 0, file);
4807                 }
4808         }
4809         
4810         if ( *info_3->helpfile ) {
4811                 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4812                         pstrcpy( file, s );
4813                         driver_unix_convert(file, conn, NULL, &bad_path, &st);
4814                         DEBUG(10,("deleting helpfile [%s]\n", s));
4815                         unlink_internals(conn, 0, file);
4816                 }
4817         }
4818         
4819         /* check if we are done removing files */
4820         
4821         if ( info_3->dependentfiles ) {
4822                 while ( info_3->dependentfiles[i][0] ) {
4823                         char *p;
4824
4825                         /* bypass the "\print$" portion of the path */
4826                         
4827                         if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4828                                 pstrcpy( file, p );
4829                                 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4830                                 DEBUG(10,("deleting dependent file [%s]\n", file));
4831                                 unlink_internals(conn, 0, file );
4832                         }
4833                         
4834                         i++;
4835                 }
4836         }
4837
4838         unbecome_user();
4839         
4840         return True;
4841 }
4842
4843 /****************************************************************************
4844  Remove a printer driver from the TDB.  This assumes that the the driver was
4845  previously looked up.
4846  ***************************************************************************/
4847
4848 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4849                               uint32 version, BOOL delete_files )
4850 {
4851         pstring         key;
4852         const char     *arch;
4853         TDB_DATA        kbuf, dbuf;
4854         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
4855
4856         /* delete the tdb data first */
4857
4858         arch = get_short_archi(info_3->environment);
4859         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4860                 arch, version, info_3->name);
4861
4862         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4863                 key, delete_files ? "TRUE" : "FALSE" ));
4864
4865         ctr.info_3 = info_3;
4866         dump_a_printer_driver( ctr, 3 );
4867
4868         kbuf.dptr=key;
4869         kbuf.dsize=strlen(key)+1;
4870
4871         /* check if the driver actually exists for this environment */
4872         
4873         dbuf = tdb_fetch( tdb_drivers, kbuf );
4874         if ( !dbuf.dptr ) {
4875                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4876                 return WERR_UNKNOWN_PRINTER_DRIVER;
4877         }
4878                 
4879         SAFE_FREE( dbuf.dptr );
4880         
4881         /* ok... the driver exists so the delete should return success */
4882                 
4883         if (tdb_delete(tdb_drivers, kbuf) == -1) {
4884                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4885                 return WERR_ACCESS_DENIED;
4886         }
4887
4888         /*
4889          * now delete any associated files if delete_files == True
4890          * even if this part failes, we return succes because the
4891          * driver doesn not exist any more
4892          */
4893
4894         if ( delete_files )
4895                 delete_driver_files( info_3, user );
4896                         
4897                 
4898         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4899
4900         return WERR_OK;
4901         }
4902         
4903 /****************************************************************************
4904  Store a security desc for a printer.
4905 ****************************************************************************/
4906
4907 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
4908 {
4909         SEC_DESC_BUF *new_secdesc_ctr = NULL;
4910         SEC_DESC_BUF *old_secdesc_ctr = NULL;
4911         prs_struct ps;
4912         TALLOC_CTX *mem_ctx = NULL;
4913         char *key;
4914         WERROR status;
4915
4916         mem_ctx = talloc_init("nt_printing_setsec");
4917         if (mem_ctx == NULL)
4918                 return WERR_NOMEM;
4919
4920         /* The old owner and group sids of the security descriptor are not
4921            present when new ACEs are added or removed by changing printer
4922            permissions through NT.  If they are NULL in the new security
4923            descriptor then copy them over from the old one. */
4924
4925         if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4926                 DOM_SID *owner_sid, *group_sid;
4927                 SEC_ACL *dacl, *sacl;
4928                 SEC_DESC *psd = NULL;
4929                 size_t size;
4930
4931                 nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr);
4932
4933                 /* Pick out correct owner and group sids */
4934
4935                 owner_sid = secdesc_ctr->sec->owner_sid ?
4936                         secdesc_ctr->sec->owner_sid :
4937                         old_secdesc_ctr->sec->owner_sid;
4938
4939                 group_sid = secdesc_ctr->sec->grp_sid ?
4940                         secdesc_ctr->sec->grp_sid :
4941                         old_secdesc_ctr->sec->grp_sid;
4942
4943                 dacl = secdesc_ctr->sec->dacl ?
4944                         secdesc_ctr->sec->dacl :
4945                         old_secdesc_ctr->sec->dacl;
4946
4947                 sacl = secdesc_ctr->sec->sacl ?
4948                         secdesc_ctr->sec->sacl :
4949                         old_secdesc_ctr->sec->sacl;
4950
4951                 /* Make a deep copy of the security descriptor */
4952
4953                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4954                                     owner_sid, group_sid,
4955                                     sacl,
4956                                     dacl,
4957                                     &size);
4958
4959                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4960         }
4961
4962         if (!new_secdesc_ctr) {
4963                 new_secdesc_ctr = secdesc_ctr;
4964         }
4965
4966         /* Store the security descriptor in a tdb */
4967
4968         prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4969                  sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4970
4971         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4972                              &ps, 1)) {
4973                 status = WERR_BADFUNC;
4974                 goto out;
4975         }
4976
4977         key = make_printers_secdesc_tdbkey( sharename );
4978
4979         if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4980                 status = WERR_OK;
4981         } else {
4982                 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
4983                 status = WERR_BADFUNC;
4984         }
4985
4986         /* Free malloc'ed memory */
4987
4988  out:
4989
4990         prs_mem_free(&ps);
4991         if (mem_ctx)
4992                 talloc_destroy(mem_ctx);
4993         return status;
4994 }
4995
4996 /****************************************************************************
4997  Construct a default security descriptor buffer for a printer.
4998 ****************************************************************************/
4999
5000 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5001 {
5002         SEC_ACE ace[5]; /* max number of ace entries */
5003         int i = 0;
5004         SEC_ACCESS sa;
5005         SEC_ACL *psa = NULL;
5006         SEC_DESC_BUF *sdb = NULL;
5007         SEC_DESC *psd = NULL;
5008         DOM_SID adm_sid;
5009         size_t sd_size;
5010
5011         /* Create an ACE where Everyone is allowed to print */
5012
5013         init_sec_access(&sa, PRINTER_ACE_PRINT);
5014         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5015                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5016
5017         /* Add the domain admins group if we are a DC */
5018         
5019         if ( IS_DC ) {
5020                 DOM_SID domadmins_sid;
5021                 
5022                 sid_copy(&domadmins_sid, get_global_sam_sid());
5023                 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5024                 
5025                 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5026                 init_sec_ace(&ace[i++], &domadmins_sid, 
5027                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5028                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5029                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5030                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5031         }
5032         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5033                 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5034
5035                 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5036                 init_sec_ace(&ace[i++], &adm_sid, 
5037                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5038                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5039                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5040                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5041         }
5042
5043         /* add BUILTIN\Administrators as FULL CONTROL */
5044
5045         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5046         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 
5047                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5048                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5049         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 
5050                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5051                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5052
5053         /* Make the security descriptor owned by the BUILTIN\Administrators */
5054
5055         /* The ACL revision number in rpc_secdesc.h differs from the one
5056            created by NT when setting ACE entries in printer
5057            descriptors.  NT4 complains about the property being edited by a
5058            NT5 machine. */
5059
5060         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5061                 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5062                         &global_sid_Builtin_Administrators, 
5063                         &global_sid_Builtin_Administrators,
5064                         NULL, psa, &sd_size);
5065         }
5066
5067         if (!psd) {
5068                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5069                 return NULL;
5070         }
5071
5072         sdb = make_sec_desc_buf(ctx, sd_size, psd);
5073
5074         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5075                  (unsigned int)sd_size));
5076
5077         return sdb;
5078 }
5079
5080 /****************************************************************************
5081  Get a security desc for a printer.
5082 ****************************************************************************/
5083
5084 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5085 {
5086         prs_struct ps;
5087         char *key;
5088         char *temp;
5089
5090         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5091                 sharename = temp + 1;
5092         }
5093
5094         /* Fetch security descriptor from tdb */
5095
5096         key = make_printers_secdesc_tdbkey( sharename  );
5097
5098         if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
5099             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5100
5101                 DEBUG(4,("using default secdesc for %s\n", sharename));
5102
5103                 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5104                         return False;
5105                 }
5106
5107                 /* Save default security descriptor for later */
5108
5109                 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
5110                                 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5111
5112                 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
5113                         tdb_prs_store(tdb_printers, key, &ps);
5114
5115                 prs_mem_free(&ps);
5116
5117                 return True;
5118         }
5119
5120         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5121            this security descriptor has been created when winbindd was
5122            down.  Take ownership of security descriptor. */
5123
5124         if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
5125                 DOM_SID owner_sid;
5126
5127                 /* Change sd owner to workgroup administrator */
5128
5129                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5130                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5131                         SEC_DESC *psd = NULL;
5132                         size_t size;
5133
5134                         /* Create new sd */
5135
5136                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5137
5138                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
5139                                             &owner_sid,
5140                                             (*secdesc_ctr)->sec->grp_sid,
5141                                             (*secdesc_ctr)->sec->sacl,
5142                                             (*secdesc_ctr)->sec->dacl,
5143                                             &size);
5144
5145                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5146
5147                         /* Swap with other one */
5148
5149                         *secdesc_ctr = new_secdesc_ctr;
5150
5151                         /* Set it */
5152
5153                         nt_printing_setsec(sharename, *secdesc_ctr);
5154                 }
5155         }
5156
5157         if (DEBUGLEVEL >= 10) {
5158                 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
5159                 int i;
5160
5161                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
5162                            sharename, the_acl->num_aces));
5163
5164                 for (i = 0; i < the_acl->num_aces; i++) {
5165                         fstring sid_str;
5166
5167                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
5168
5169                         DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5170                                    the_acl->ace[i].type, the_acl->ace[i].flags, 
5171                                    the_acl->ace[i].info.mask)); 
5172                 }
5173         }
5174
5175         prs_mem_free(&ps);
5176         return True;
5177 }
5178
5179 /* error code:
5180         0: everything OK
5181         1: level not implemented
5182         2: file doesn't exist
5183         3: can't allocate memory
5184         4: can't free memory
5185         5: non existant struct
5186 */
5187
5188 /*
5189         A printer and a printer driver are 2 different things.
5190         NT manages them separatelly, Samba does the same.
5191         Why ? Simply because it's easier and it makes sense !
5192         
5193         Now explanation: You have 3 printers behind your samba server,
5194         2 of them are the same make and model (laser A and B). But laser B
5195         has an 3000 sheet feeder and laser A doesn't such an option.
5196         Your third printer is an old dot-matrix model for the accounting :-).
5197         
5198         If the /usr/local/samba/lib directory (default dir), you will have
5199         5 files to describe all of this.
5200         
5201         3 files for the printers (1 by printer):
5202                 NTprinter_laser A
5203                 NTprinter_laser B
5204                 NTprinter_accounting
5205         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5206                 NTdriver_printer model X
5207                 NTdriver_printer model Y
5208
5209 jfm: I should use this comment for the text file to explain
5210         same thing for the forms BTW.
5211         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5212
5213 */
5214
5215 /* Convert generic access rights to printer object specific access rights.
5216    It turns out that NT4 security descriptors use generic access rights and
5217    NT5 the object specific ones. */
5218
5219 void map_printer_permissions(SEC_DESC *sd)
5220 {
5221         int i;
5222
5223         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5224                 se_map_generic(&sd->dacl->ace[i].info.mask,
5225                                &printer_generic_mapping);
5226         }
5227 }
5228
5229 /****************************************************************************
5230  Check a user has permissions to perform the given operation.  We use the
5231  permission constants defined in include/rpc_spoolss.h to check the various
5232  actions we perform when checking printer access.
5233
5234    PRINTER_ACCESS_ADMINISTER:
5235        print_queue_pause, print_queue_resume, update_printer_sec,
5236        update_printer, spoolss_addprinterex_level_2,
5237        _spoolss_setprinterdata
5238
5239    PRINTER_ACCESS_USE:
5240        print_job_start
5241
5242    JOB_ACCESS_ADMINISTER:
5243        print_job_delete, print_job_pause, print_job_resume,
5244        print_queue_purge
5245
5246   Try access control in the following order (for performance reasons):
5247     1)  root ans SE_PRINT_OPERATOR can do anything (easy check) 
5248     2)  check security descriptor (bit comparisons in memory)
5249     3)  "printer admins" (may result in numerous calls to winbind)
5250
5251  ****************************************************************************/
5252 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5253 {
5254         SEC_DESC_BUF *secdesc = NULL;
5255         uint32 access_granted;
5256         NTSTATUS status;
5257         BOOL result;
5258         const char *pname;
5259         TALLOC_CTX *mem_ctx = NULL;
5260         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5261         
5262         /* If user is NULL then use the current_user structure */
5263
5264         if (!user)
5265                 user = &current_user;
5266
5267         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5268
5269         if ( user->uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5270                 return True;
5271         }
5272
5273         /* Get printer name */
5274
5275         pname = PRINTERNAME(snum);
5276
5277         if (!pname || !*pname) {
5278                 errno = EACCES;
5279                 return False;
5280         }
5281
5282         /* Get printer security descriptor */
5283
5284         if(!(mem_ctx = talloc_init("print_access_check"))) {
5285                 errno = ENOMEM;
5286                 return False;
5287         }
5288
5289         nt_printing_getsec(mem_ctx, pname, &secdesc);
5290
5291         if (access_type == JOB_ACCESS_ADMINISTER) {
5292                 SEC_DESC_BUF *parent_secdesc = secdesc;
5293
5294                 /* Create a child security descriptor to check permissions
5295                    against.  This is because print jobs are child objects
5296                    objects of a printer. */
5297
5298                 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5299
5300                 /* Now this is the bit that really confuses me.  The access
5301                    type needs to be changed from JOB_ACCESS_ADMINISTER to
5302                    PRINTER_ACCESS_ADMINISTER for this to work.  Something
5303                    to do with the child (job) object becoming like a
5304                    printer??  -tpot */
5305
5306                 access_type = PRINTER_ACCESS_ADMINISTER;
5307         }
5308         
5309         /* Check access */
5310         
5311         map_printer_permissions(secdesc->sec);
5312
5313         result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5314                                  &access_granted, &status);
5315
5316         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5317
5318         /* see if we need to try the printer admin list */
5319
5320         if ( access_granted == 0 ) {
5321                 if ( user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups) )
5322                         return True;
5323         }
5324
5325         talloc_destroy(mem_ctx);
5326         
5327         if (!result)
5328                 errno = EACCES;
5329
5330         return result;
5331 }
5332
5333 /****************************************************************************
5334  Check the time parameters allow a print operation.
5335 *****************************************************************************/
5336
5337 BOOL print_time_access_check(int snum)
5338 {
5339         NT_PRINTER_INFO_LEVEL *printer = NULL;
5340         BOOL ok = False;
5341         time_t now = time(NULL);
5342         struct tm *t;
5343         uint32 mins;
5344
5345         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5346                 return False;
5347
5348         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5349                 ok = True;
5350
5351         t = gmtime(&now);
5352         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5353
5354         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5355                 ok = True;
5356
5357         free_a_printer(&printer, 2);
5358
5359         if (!ok)
5360                 errno = EACCES;
5361
5362         return ok;
5363 }
5364
5365 /****************************************************************************
5366  Fill in the servername sent in the _spoolss_open_printer_ex() call
5367 ****************************************************************************/
5368
5369 char* get_server_name( Printer_entry *printer )
5370 {
5371         return printer->servername;
5372 }
5373
5374