Initial import
[samba] / source / printing / nt_printing.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2000.
6  *  Copyright (C) Gerald Carter                2002-2005.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 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, SPL_ARCH_WIN40) == 0) {
1390                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1391                 *perr = WERR_OK;
1392                 return 0;
1393         }
1394
1395         /* If architecture is Windows x64, the version is always 3. */
1396         if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1397                 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1398                 *perr = WERR_OK;
1399                 return 3;
1400         }
1401
1402         /*
1403          * Connect to the print$ share under the same account as the user connected
1404          * to the rpc pipe. Note we must still be root to do this.
1405          */
1406
1407         /* Null password is ok - we are already an authenticated user... */
1408         null_pw = data_blob(NULL, 0);
1409         fstrcpy(res_type, "A:");
1410         become_root();
1411         conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1412         unbecome_root();
1413
1414         if (conn == NULL) {
1415                 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1416                 *perr = ntstatus_to_werror(nt_status);
1417                 return -1;
1418         }
1419
1420         /* We are temporarily becoming the connection user. */
1421         if (!become_user(conn, user->vuid)) {
1422                 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1423                 *perr = WERR_ACCESS_DENIED;
1424                 return -1;
1425         }
1426
1427         /* Open the driver file (Portable Executable format) and determine the
1428          * deriver the cversion. */
1429         slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1430
1431         driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
1432
1433         if ( !vfs_file_exist( conn, driverpath, &st ) ) {
1434                 *perr = WERR_BADFILE;
1435                 goto error_exit;
1436         }
1437
1438         fsp = open_file_ntcreate(conn, driverpath, &st,
1439                                 FILE_GENERIC_READ,
1440                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1441                                 FILE_OPEN,
1442                                 0,
1443                                 FILE_ATTRIBUTE_NORMAL,
1444                                 INTERNAL_OPEN_ONLY,
1445                                 NULL);
1446
1447         if (!fsp) {
1448                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1449                                 driverpath, errno));
1450                 *perr = WERR_ACCESS_DENIED;
1451                 goto error_exit;
1452         } else {
1453                 uint32 major;
1454                 uint32 minor;
1455                 int    ret = get_file_version(fsp, driverpath, &major, &minor);
1456                 if (ret == -1) goto error_exit;
1457
1458                 if (!ret) {
1459                         DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1460                         goto error_exit;
1461                 }
1462
1463                 /*
1464                  * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1465                  * for more details. Version in this case is not just the version of the 
1466                  * file, but the version in the sense of kernal mode (2) vs. user mode
1467                  * (3) drivers. Other bits of the version fields are the version info. 
1468                  * JRR 010716
1469                 */
1470                 cversion = major & 0x0000ffff;
1471                 switch (cversion) {
1472                         case 2: /* WinNT drivers */
1473                         case 3: /* Win2K drivers */
1474                                 break;
1475                         
1476                         default:
1477                                 DEBUG(6,("get_correct_cversion: cversion invalid [%s]  cversion = %d\n", 
1478                                         driverpath, cversion));
1479                                 goto error_exit;
1480                 }
1481
1482                 DEBUG(10,("get_correct_cversion: Version info found [%s]  major = 0x%x  minor = 0x%x\n",
1483                                   driverpath, major, minor));
1484         }
1485
1486         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1487                 driverpath, cversion));
1488
1489         close_file(fsp, True);
1490         close_cnum(conn, user->vuid);
1491         unbecome_user();
1492         *perr = WERR_OK;
1493         return cversion;
1494
1495
1496   error_exit:
1497
1498         if(fsp)
1499                 close_file(fsp, True);
1500
1501         close_cnum(conn, user->vuid);
1502         unbecome_user();
1503         return -1;
1504 }
1505
1506 /****************************************************************************
1507 ****************************************************************************/
1508 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1509                                                                                          struct current_user *user)
1510 {
1511         const char *architecture;
1512         fstring new_name;
1513         char *p;
1514         int i;
1515         WERROR err;
1516
1517         /* clean up the driver name.
1518          * we can get .\driver.dll
1519          * or worse c:\windows\system\driver.dll !
1520          */
1521         /* using an intermediate string to not have overlaping memcpy()'s */
1522         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1523                 fstrcpy(new_name, p+1);
1524                 fstrcpy(driver->driverpath, new_name);
1525         }
1526
1527         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1528                 fstrcpy(new_name, p+1);
1529                 fstrcpy(driver->datafile, new_name);
1530         }
1531
1532         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1533                 fstrcpy(new_name, p+1);
1534                 fstrcpy(driver->configfile, new_name);
1535         }
1536
1537         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1538                 fstrcpy(new_name, p+1);
1539                 fstrcpy(driver->helpfile, new_name);
1540         }
1541
1542         if (driver->dependentfiles) {
1543                 for (i=0; *driver->dependentfiles[i]; i++) {
1544                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1545                                 fstrcpy(new_name, p+1);
1546                                 fstrcpy(driver->dependentfiles[i], new_name);
1547                         }
1548                 }
1549         }
1550
1551         architecture = get_short_archi(driver->environment);
1552         
1553         /* jfm:7/16/2000 the client always sends the cversion=0.
1554          * The server should check which version the driver is by reading
1555          * the PE header of driver->driverpath.
1556          *
1557          * For Windows 95/98 the version is 0 (so the value sent is correct)
1558          * For Windows NT (the architecture doesn't matter)
1559          *      NT 3.1: cversion=0
1560          *      NT 3.5/3.51: cversion=1
1561          *      NT 4: cversion=2
1562          *      NT2K: cversion=3
1563          */
1564         if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1565                         return err;
1566
1567         return WERR_OK;
1568 }
1569         
1570 /****************************************************************************
1571 ****************************************************************************/
1572 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1573 {
1574         const char *architecture;
1575         fstring new_name;
1576         char *p;
1577         int i;
1578         WERROR err;
1579
1580         /* clean up the driver name.
1581          * we can get .\driver.dll
1582          * or worse c:\windows\system\driver.dll !
1583          */
1584         /* using an intermediate string to not have overlaping memcpy()'s */
1585         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1586                 fstrcpy(new_name, p+1);
1587                 fstrcpy(driver->driverpath, new_name);
1588         }
1589
1590         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1591                 fstrcpy(new_name, p+1);
1592                 fstrcpy(driver->datafile, new_name);
1593         }
1594
1595         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1596                 fstrcpy(new_name, p+1);
1597                 fstrcpy(driver->configfile, new_name);
1598         }
1599
1600         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1601                 fstrcpy(new_name, p+1);
1602                 fstrcpy(driver->helpfile, new_name);
1603         }
1604
1605         if (driver->dependentfiles) {
1606                 for (i=0; *driver->dependentfiles[i]; i++) {
1607                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1608                                 fstrcpy(new_name, p+1);
1609                                 fstrcpy(driver->dependentfiles[i], new_name);
1610                         }
1611                 }
1612         }
1613
1614         architecture = get_short_archi(driver->environment);
1615
1616         /* jfm:7/16/2000 the client always sends the cversion=0.
1617          * The server should check which version the driver is by reading
1618          * the PE header of driver->driverpath.
1619          *
1620          * For Windows 95/98 the version is 0 (so the value sent is correct)
1621          * For Windows NT (the architecture doesn't matter)
1622          *      NT 3.1: cversion=0
1623          *      NT 3.5/3.51: cversion=1
1624          *      NT 4: cversion=2
1625          *      NT2K: cversion=3
1626          */
1627
1628         if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1629                         return err;
1630
1631         return WERR_OK;
1632 }
1633
1634 /****************************************************************************
1635 ****************************************************************************/
1636 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1637                                                           uint32 level, struct current_user *user)
1638 {
1639         switch (level) {
1640                 case 3:
1641                 {
1642                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1643                         driver=driver_abstract.info_3;
1644                         return clean_up_driver_struct_level_3(driver, user);
1645                 }
1646                 case 6:
1647                 {
1648                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1649                         driver=driver_abstract.info_6;
1650                         return clean_up_driver_struct_level_6(driver, user);
1651                 }
1652                 default:
1653                         return WERR_INVALID_PARAM;
1654         }
1655 }
1656
1657 /****************************************************************************
1658  This function sucks and should be replaced. JRA.
1659 ****************************************************************************/
1660
1661 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1662 {
1663     dst->cversion  = src->version;
1664
1665     fstrcpy( dst->name, src->name);
1666     fstrcpy( dst->environment, src->environment);
1667     fstrcpy( dst->driverpath, src->driverpath);
1668     fstrcpy( dst->datafile, src->datafile);
1669     fstrcpy( dst->configfile, src->configfile);
1670     fstrcpy( dst->helpfile, src->helpfile);
1671     fstrcpy( dst->monitorname, src->monitorname);
1672     fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1673     dst->dependentfiles = src->dependentfiles;
1674 }
1675
1676 #if 0 /* Debugging function */
1677
1678 static char* ffmt(unsigned char *c){
1679         int i;
1680         static char ffmt_str[17];
1681
1682         for (i=0; i<16; i++) {
1683                 if ((c[i] < ' ') || (c[i] > '~'))
1684                         ffmt_str[i]='.';
1685                 else
1686                         ffmt_str[i]=c[i];
1687         }
1688     ffmt_str[16]='\0';
1689         return ffmt_str;
1690 }
1691
1692 #endif
1693
1694 /****************************************************************************
1695 ****************************************************************************/
1696 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, 
1697                                   struct current_user *user, WERROR *perr)
1698 {
1699         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1700         NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1701         const char *architecture;
1702         pstring new_dir;
1703         pstring old_name;
1704         pstring new_name;
1705         DATA_BLOB null_pw;
1706         connection_struct *conn;
1707         NTSTATUS nt_status;
1708         pstring inbuf;
1709         pstring outbuf;
1710         fstring res_type;
1711         BOOL bad_path;
1712         SMB_STRUCT_STAT st;
1713         int ver = 0;
1714         int i;
1715         int err;
1716
1717         memset(inbuf, '\0', sizeof(inbuf));
1718         memset(outbuf, '\0', sizeof(outbuf));
1719         *perr = WERR_OK;
1720
1721         if (level==3)
1722                 driver=driver_abstract.info_3;
1723         else if (level==6) {
1724                 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1725                 driver = &converted_driver;
1726         } else {
1727                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1728                 return WERR_UNKNOWN_LEVEL;
1729         }
1730
1731         architecture = get_short_archi(driver->environment);
1732
1733         /*
1734          * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1735          * Note we must be root to do this.
1736          */
1737
1738         null_pw = data_blob(NULL, 0);
1739         fstrcpy(res_type, "A:");
1740         become_root();
1741         conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1742         unbecome_root();
1743
1744         if (conn == NULL) {
1745                 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1746                 *perr = ntstatus_to_werror(nt_status);
1747                 return WERR_NO_SUCH_SHARE;
1748         }
1749
1750         /*
1751          * Save who we are - we are temporarily becoming the connection user.
1752          */
1753
1754         if (!become_user(conn, conn->vuid)) {
1755                 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1756                 return WERR_ACCESS_DENIED;
1757         }
1758
1759         /*
1760          * make the directories version and version\driver_name
1761          * under the architecture directory.
1762          */
1763         DEBUG(5,("Creating first directory\n"));
1764         slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1765         driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
1766         mkdir_internal(conn, new_dir, bad_path);
1767
1768         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1769          * listed for this driver which has already been moved, skip it (note:
1770          * drivers may list the same file name several times. Then check if the
1771          * file already exists in archi\cversion\, if so, check that the version
1772          * info (or time stamps if version info is unavailable) is newer (or the
1773          * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1774          * Otherwise, delete the file.
1775          *
1776          * If a file is not moved to archi\cversion\ because of an error, all the
1777          * rest of the 'unmoved' driver files are removed from archi\. If one or
1778          * more of the driver's files was already moved to archi\cversion\, it
1779          * potentially leaves the driver in a partially updated state. Version
1780          * trauma will most likely occur if an client attempts to use any printer
1781          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1782          * done is appropriate... later JRR
1783          */
1784
1785         DEBUG(5,("Moving files now !\n"));
1786
1787         if (driver->driverpath && strlen(driver->driverpath)) {
1788                 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);      
1789                 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);   
1790                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1791                         driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1792                         if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1793                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1794                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1795                                                 new_name, old_name));
1796                                 *perr = WERR_ACCESS_DENIED;
1797                                 ver = -1;
1798                         }
1799                 } 
1800         }
1801
1802         if (driver->datafile && strlen(driver->datafile)) {
1803                 if (!strequal(driver->datafile, driver->driverpath)) {
1804                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);        
1805                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);     
1806                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1807                                 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1808                                 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1809                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1810                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1811                                                         new_name, old_name));
1812                                         *perr = WERR_ACCESS_DENIED;
1813                                         ver = -1;
1814                                 }
1815                         }
1816                 }
1817         }
1818
1819         if (driver->configfile && strlen(driver->configfile)) {
1820                 if (!strequal(driver->configfile, driver->driverpath) &&
1821                         !strequal(driver->configfile, driver->datafile)) {
1822                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);      
1823                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);   
1824                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1825                                 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1826                                 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1827                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1828                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1829                                                         new_name, old_name));
1830                                         *perr = WERR_ACCESS_DENIED;
1831                                         ver = -1;
1832                                 }
1833                         }
1834                 }
1835         }
1836
1837         if (driver->helpfile && strlen(driver->helpfile)) {
1838                 if (!strequal(driver->helpfile, driver->driverpath) &&
1839                         !strequal(driver->helpfile, driver->datafile) &&
1840                         !strequal(driver->helpfile, driver->configfile)) {
1841                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);        
1842                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);     
1843                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1844                                 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1845                                 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1846                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1847                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1848                                                         new_name, old_name));
1849                                         *perr = WERR_ACCESS_DENIED;
1850                                         ver = -1;
1851                                 }
1852                         }
1853                 }
1854         }
1855
1856         if (driver->dependentfiles) {
1857                 for (i=0; *driver->dependentfiles[i]; i++) {
1858                         if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1859                                 !strequal(driver->dependentfiles[i], driver->datafile) &&
1860                                 !strequal(driver->dependentfiles[i], driver->configfile) &&
1861                                 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1862                                 int j;
1863                                 for (j=0; j < i; j++) {
1864                                         if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1865                                                 goto NextDriver;
1866                                         }
1867                                 }
1868
1869                                 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);       
1870                                 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);    
1871                                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1872                                         driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1873                                         if ( !copy_file(new_name, old_name, conn,
1874                                                         OPENX_FILE_EXISTS_TRUNCATE|
1875                                                         OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1876                                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1877                                                                 new_name, old_name));
1878                                                 *perr = WERR_ACCESS_DENIED;
1879                                                 ver = -1;
1880                                         }
1881                                 }
1882                         }
1883                 NextDriver: ;
1884                 }
1885         }
1886
1887         close_cnum(conn, user->vuid);
1888         unbecome_user();
1889
1890         return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
1891 }
1892
1893 /****************************************************************************
1894 ****************************************************************************/
1895 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1896 {
1897         int len, buflen;
1898         const char *architecture;
1899         pstring directory;
1900         fstring temp_name;
1901         pstring key;
1902         char *buf;
1903         int i, ret;
1904         TDB_DATA kbuf, dbuf;
1905
1906         architecture = get_short_archi(driver->environment);
1907
1908         /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1909          * \\server is added in the rpc server layer.
1910          * It does make sense to NOT store the server's name in the printer TDB.
1911          */
1912
1913         slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1914
1915         /* .inf files do not always list a file for each of the four standard files. 
1916          * Don't prepend a path to a null filename, or client claims:
1917          *   "The server on which the printer resides does not have a suitable 
1918          *   <printer driver name> printer driver installed. Click OK if you 
1919          *   wish to install the driver on your local machine."
1920          */
1921         if (strlen(driver->driverpath)) {
1922                 fstrcpy(temp_name, driver->driverpath);
1923                 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1924         }
1925
1926         if (strlen(driver->datafile)) {
1927                 fstrcpy(temp_name, driver->datafile);
1928                 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1929         }
1930
1931         if (strlen(driver->configfile)) {
1932                 fstrcpy(temp_name, driver->configfile);
1933                 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1934         }
1935
1936         if (strlen(driver->helpfile)) {
1937                 fstrcpy(temp_name, driver->helpfile);
1938                 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1939         }
1940
1941         if (driver->dependentfiles) {
1942                 for (i=0; *driver->dependentfiles[i]; i++) {
1943                         fstrcpy(temp_name, driver->dependentfiles[i]);
1944                         slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1945                 }
1946         }
1947
1948         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1949
1950         DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1951
1952         buf = NULL;
1953         len = buflen = 0;
1954
1955  again:
1956         len = 0;
1957         len += tdb_pack(buf+len, buflen-len, "dffffffff",
1958                         driver->cversion,
1959                         driver->name,
1960                         driver->environment,
1961                         driver->driverpath,
1962                         driver->datafile,
1963                         driver->configfile,
1964                         driver->helpfile,
1965                         driver->monitorname,
1966                         driver->defaultdatatype);
1967
1968         if (driver->dependentfiles) {
1969                 for (i=0; *driver->dependentfiles[i]; i++) {
1970                         len += tdb_pack(buf+len, buflen-len, "f",
1971                                         driver->dependentfiles[i]);
1972                 }
1973         }
1974
1975         if (len != buflen) {
1976                 char *tb;
1977
1978                 tb = (char *)SMB_REALLOC(buf, len);
1979                 if (!tb) {
1980                         DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1981                         ret = -1;
1982                         goto done;
1983                 }
1984                 else buf = tb;
1985                 buflen = len;
1986                 goto again;
1987         }
1988
1989
1990         kbuf.dptr = key;
1991         kbuf.dsize = strlen(key)+1;
1992         dbuf.dptr = buf;
1993         dbuf.dsize = len;
1994         
1995         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1996
1997 done:
1998         if (ret)
1999                 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2000
2001         SAFE_FREE(buf);
2002         return ret;
2003 }
2004
2005 /****************************************************************************
2006 ****************************************************************************/
2007 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2008 {
2009         NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2010
2011         ZERO_STRUCT(info3);
2012         info3.cversion = driver->version;
2013         fstrcpy(info3.name,driver->name);
2014         fstrcpy(info3.environment,driver->environment);
2015         fstrcpy(info3.driverpath,driver->driverpath);
2016         fstrcpy(info3.datafile,driver->datafile);
2017         fstrcpy(info3.configfile,driver->configfile);
2018         fstrcpy(info3.helpfile,driver->helpfile);
2019         fstrcpy(info3.monitorname,driver->monitorname);
2020         fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2021         info3.dependentfiles = driver->dependentfiles;
2022
2023         return add_a_printer_driver_3(&info3);
2024 }
2025
2026
2027 /****************************************************************************
2028 ****************************************************************************/
2029 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2030 {
2031         NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2032
2033         ZERO_STRUCT(info);
2034
2035         fstrcpy(info.name, driver);
2036         fstrcpy(info.defaultdatatype, "RAW");
2037         
2038         fstrcpy(info.driverpath, "");
2039         fstrcpy(info.datafile, "");
2040         fstrcpy(info.configfile, "");
2041         fstrcpy(info.helpfile, "");
2042
2043         if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2044                 return WERR_NOMEM;
2045
2046         memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2047         fstrcpy(info.dependentfiles[0], "");
2048
2049         *info_ptr = memdup(&info, sizeof(info));
2050         
2051         return WERR_OK;
2052 }
2053
2054 /****************************************************************************
2055 ****************************************************************************/
2056 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
2057 {
2058         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2059         TDB_DATA kbuf, dbuf;
2060         const char *architecture;
2061         int len = 0;
2062         int i;
2063         pstring key;
2064
2065         ZERO_STRUCT(driver);
2066
2067         architecture = get_short_archi(arch);
2068
2069         if ( !architecture )
2070                 return WERR_UNKNOWN_PRINTER_DRIVER;
2071         
2072         /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2073         
2074         if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2075                 version = 0;
2076
2077         DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2078
2079         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
2080
2081         kbuf.dptr = key;
2082         kbuf.dsize = strlen(key)+1;
2083         
2084         dbuf = tdb_fetch(tdb_drivers, kbuf);
2085         if (!dbuf.dptr) 
2086                 return WERR_UNKNOWN_PRINTER_DRIVER;
2087
2088         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2089                           &driver.cversion,
2090                           driver.name,
2091                           driver.environment,
2092                           driver.driverpath,
2093                           driver.datafile,
2094                           driver.configfile,
2095                           driver.helpfile,
2096                           driver.monitorname,
2097                           driver.defaultdatatype);
2098
2099         i=0;
2100         while (len < dbuf.dsize) {
2101                 fstring *tddfs;
2102
2103                 tddfs = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2104                 if ( !tddfs ) {
2105                         DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2106                         break;
2107                 }
2108                 else 
2109                         driver.dependentfiles = tddfs;
2110
2111                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2112                                   &driver.dependentfiles[i]);
2113                 i++;
2114         }
2115         
2116         if ( driver.dependentfiles )
2117                 fstrcpy( driver.dependentfiles[i], "" );
2118
2119         SAFE_FREE(dbuf.dptr);
2120
2121         if (len != dbuf.dsize) {
2122                 SAFE_FREE(driver.dependentfiles);
2123
2124                 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2125         }
2126
2127         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2128
2129         return WERR_OK;
2130 }
2131
2132 /****************************************************************************
2133  Debugging function, dump at level 6 the struct in the logs.
2134 ****************************************************************************/
2135
2136 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2137 {
2138         uint32 result;
2139         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2140         int i;
2141         
2142         DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2143         
2144         switch (level)
2145         {
2146                 case 3:
2147                 {
2148                         if (driver.info_3 == NULL)
2149                                 result=5;
2150                         else {
2151                                 info3=driver.info_3;
2152                         
2153                                 DEBUGADD(20,("version:[%d]\n",         info3->cversion));
2154                                 DEBUGADD(20,("name:[%s]\n",            info3->name));
2155                                 DEBUGADD(20,("environment:[%s]\n",     info3->environment));
2156                                 DEBUGADD(20,("driverpath:[%s]\n",      info3->driverpath));
2157                                 DEBUGADD(20,("datafile:[%s]\n",        info3->datafile));
2158                                 DEBUGADD(20,("configfile:[%s]\n",      info3->configfile));
2159                                 DEBUGADD(20,("helpfile:[%s]\n",        info3->helpfile));
2160                                 DEBUGADD(20,("monitorname:[%s]\n",     info3->monitorname));
2161                                 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2162                                 
2163                                 for (i=0; info3->dependentfiles &&
2164                                           *info3->dependentfiles[i]; i++) {
2165                                         DEBUGADD(20,("dependentfile:[%s]\n",
2166                                                       info3->dependentfiles[i]));
2167                                 }
2168                                 result=0;
2169                         }
2170                         break;
2171                 }
2172                 default:
2173                         DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2174                         result=1;
2175                         break;
2176         }
2177         
2178         return result;
2179 }
2180
2181 /****************************************************************************
2182 ****************************************************************************/
2183 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
2184 {
2185         int len = 0;
2186
2187         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2188
2189         if (!nt_devmode)
2190                 return len;
2191
2192         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2193                         nt_devmode->devicename,
2194                         nt_devmode->formname,
2195
2196                         nt_devmode->specversion,
2197                         nt_devmode->driverversion,
2198                         nt_devmode->size,
2199                         nt_devmode->driverextra,
2200                         nt_devmode->orientation,
2201                         nt_devmode->papersize,
2202                         nt_devmode->paperlength,
2203                         nt_devmode->paperwidth,
2204                         nt_devmode->scale,
2205                         nt_devmode->copies,
2206                         nt_devmode->defaultsource,
2207                         nt_devmode->printquality,
2208                         nt_devmode->color,
2209                         nt_devmode->duplex,
2210                         nt_devmode->yresolution,
2211                         nt_devmode->ttoption,
2212                         nt_devmode->collate,
2213                         nt_devmode->logpixels,
2214                         
2215                         nt_devmode->fields,
2216                         nt_devmode->bitsperpel,
2217                         nt_devmode->pelswidth,
2218                         nt_devmode->pelsheight,
2219                         nt_devmode->displayflags,
2220                         nt_devmode->displayfrequency,
2221                         nt_devmode->icmmethod,
2222                         nt_devmode->icmintent,
2223                         nt_devmode->mediatype,
2224                         nt_devmode->dithertype,
2225                         nt_devmode->reserved1,
2226                         nt_devmode->reserved2,
2227                         nt_devmode->panningwidth,
2228                         nt_devmode->panningheight,
2229                         nt_devmode->nt_dev_private);
2230
2231         
2232         if (nt_devmode->nt_dev_private) {
2233                 len += tdb_pack(buf+len, buflen-len, "B",
2234                                 nt_devmode->driverextra,
2235                                 nt_devmode->nt_dev_private);
2236         }
2237
2238         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2239
2240         return len;
2241 }
2242
2243 /****************************************************************************
2244  Pack all values in all printer keys
2245  ***************************************************************************/
2246  
2247 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
2248 {
2249         int             len = 0;
2250         int             i, j;
2251         REGISTRY_VALUE  *val;
2252         REGVAL_CTR      *val_ctr;
2253         pstring         path;
2254         int             num_values;
2255
2256         if ( !data )
2257                 return 0;
2258
2259         /* loop over all keys */
2260                 
2261         for ( i=0; i<data->num_keys; i++ ) {    
2262                 val_ctr = data->keys[i].values;
2263                 num_values = regval_ctr_numvals( val_ctr );
2264
2265                 /* pack the keyname followed by a empty value */
2266
2267                 len += tdb_pack(buf+len, buflen-len, "pPdB", 
2268                                 &data->keys[i].name,
2269                                 data->keys[i].name, 
2270                                 REG_NONE,
2271                                 0,
2272                                 NULL);
2273                 
2274                 /* now loop over all values */
2275                 
2276                 for ( j=0; j<num_values; j++ ) {
2277                         /* pathname should be stored as <key>\<value> */
2278                         
2279                         val = regval_ctr_specific_value( val_ctr, j );
2280                         pstrcpy( path, data->keys[i].name );
2281                         pstrcat( path, "\\" );
2282                         pstrcat( path, regval_name(val) );
2283                         
2284                         len += tdb_pack(buf+len, buflen-len, "pPdB",
2285                                         val,
2286                                         path,
2287                                         regval_type(val),
2288                                         regval_size(val),
2289                                         regval_data_p(val) );
2290
2291                         DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2292                 }
2293         
2294         }
2295
2296         /* terminator */
2297         
2298         len += tdb_pack(buf+len, buflen-len, "p", NULL);
2299
2300         return len;
2301 }
2302
2303
2304 /****************************************************************************
2305  Delete a printer - this just deletes the printer info file, any open
2306  handles are not affected.
2307 ****************************************************************************/
2308
2309 uint32 del_a_printer(const char *sharename)
2310 {
2311         pstring key;
2312         TDB_DATA kbuf;
2313         pstring printdb_path;
2314
2315         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2316         kbuf.dptr=key;
2317         kbuf.dsize=strlen(key)+1;
2318         tdb_delete(tdb_printers, kbuf);
2319
2320         slprintf(key, sizeof(key)-1, "%s%s", SECDESC_PREFIX, sharename);
2321         kbuf.dptr=key;
2322         kbuf.dsize=strlen(key)+1;
2323         tdb_delete(tdb_printers, kbuf);
2324
2325         close_all_print_db();
2326
2327         if (geteuid() == 0) {
2328                 pstrcpy(printdb_path, lock_path("printing/"));
2329                 pstrcat(printdb_path, sharename);
2330                 pstrcat(printdb_path, ".tdb");
2331
2332                 unlink(printdb_path);
2333         }
2334
2335         return 0;
2336 }
2337
2338 /****************************************************************************
2339 ****************************************************************************/
2340 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2341 {
2342         char *buf;
2343         int buflen, len;
2344         WERROR ret;
2345         TDB_DATA kbuf, dbuf;
2346         
2347         /*
2348          * in addprinter: no servername and the printer is the name
2349          * in setprinter: servername is \\server
2350          *                and printer is \\server\\printer
2351          *
2352          * Samba manages only local printers.
2353          * we currently don't support things like i
2354          * path=\\other_server\printer
2355          *
2356          * We only store the printername, not \\server\printername
2357          */
2358
2359         if ( info->servername[0] != '\0' ) {
2360                 trim_string(info->printername, info->servername, NULL);
2361                 trim_char(info->printername, '\\', '\0');
2362                 info->servername[0]='\0';
2363         }
2364
2365         /*
2366          * JFM: one day I'll forget.
2367          * below that's info->portname because that's the SAMBA sharename
2368          * and I made NT 'thinks' it's the portname
2369          * the info->sharename is the thing you can name when you add a printer
2370          * that's the short-name when you create shared printer for 95/98
2371          * So I've made a limitation in SAMBA: you can only have 1 printer model
2372          * behind a SAMBA share.
2373          */
2374
2375         buf = NULL;
2376         buflen = 0;
2377
2378  again: 
2379         len = 0;
2380         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2381                         info->attributes,
2382                         info->priority,
2383                         info->default_priority,
2384                         info->starttime,
2385                         info->untiltime,
2386                         info->status,
2387                         info->cjobs,
2388                         info->averageppm,
2389                         info->changeid,
2390                         info->c_setprinter,
2391                         info->setuptime,
2392                         info->servername,
2393                         info->printername,
2394                         info->sharename,
2395                         info->portname,
2396                         info->drivername,
2397                         info->comment,
2398                         info->location,
2399                         info->sepfile,
2400                         info->printprocessor,
2401                         info->datatype,
2402                         info->parameters);
2403
2404         len += pack_devicemode(info->devmode, buf+len, buflen-len);
2405         
2406         len += pack_values( info->data, buf+len, buflen-len );
2407
2408         if (buflen != len) {
2409                 char *tb;
2410
2411                 tb = (char *)SMB_REALLOC(buf, len);
2412                 if (!tb) {
2413                         DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2414                         ret = WERR_NOMEM;
2415                         goto done;
2416                 }
2417                 else buf = tb;
2418                 buflen = len;
2419                 goto again;
2420         }
2421         
2422
2423         kbuf = make_printer_tdbkey( info->sharename );
2424
2425         dbuf.dptr = buf;
2426         dbuf.dsize = len;
2427
2428         ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2429
2430 done:
2431         if (!W_ERROR_IS_OK(ret))
2432                 DEBUG(8, ("error updating printer to tdb on disk\n"));
2433
2434         SAFE_FREE(buf);
2435
2436         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2437                  info->sharename, info->drivername, info->portname, len));
2438
2439         return ret;
2440 }
2441
2442
2443 /****************************************************************************
2444  Malloc and return an NT devicemode.
2445 ****************************************************************************/
2446
2447 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2448 {
2449
2450         char adevice[MAXDEVICENAME];
2451         NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2452
2453         if (nt_devmode == NULL) {
2454                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2455                 return NULL;
2456         }
2457
2458         ZERO_STRUCTP(nt_devmode);
2459
2460         slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2461         fstrcpy(nt_devmode->devicename, adevice);       
2462         
2463         fstrcpy(nt_devmode->formname, "Letter");
2464
2465         nt_devmode->specversion      = 0x0401;
2466         nt_devmode->driverversion    = 0x0400;
2467         nt_devmode->size             = 0x00DC;
2468         nt_devmode->driverextra      = 0x0000;
2469         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY |
2470                                        DEFAULTSOURCE | COPIES | SCALE |
2471                                        PAPERSIZE | ORIENTATION;
2472         nt_devmode->orientation      = 1;
2473         nt_devmode->papersize        = PAPER_LETTER;
2474         nt_devmode->paperlength      = 0;
2475         nt_devmode->paperwidth       = 0;
2476         nt_devmode->scale            = 0x64;
2477         nt_devmode->copies           = 1;
2478         nt_devmode->defaultsource    = BIN_FORMSOURCE;
2479         nt_devmode->printquality     = RES_HIGH;           /* 0x0258 */
2480         nt_devmode->color            = COLOR_MONOCHROME;
2481         nt_devmode->duplex           = DUP_SIMPLEX;
2482         nt_devmode->yresolution      = 0;
2483         nt_devmode->ttoption         = TT_SUBDEV;
2484         nt_devmode->collate          = COLLATE_FALSE;
2485         nt_devmode->icmmethod        = 0;
2486         nt_devmode->icmintent        = 0;
2487         nt_devmode->mediatype        = 0;
2488         nt_devmode->dithertype       = 0;
2489
2490         /* non utilisés par un driver d'imprimante */
2491         nt_devmode->logpixels        = 0;
2492         nt_devmode->bitsperpel       = 0;
2493         nt_devmode->pelswidth        = 0;
2494         nt_devmode->pelsheight       = 0;
2495         nt_devmode->displayflags     = 0;
2496         nt_devmode->displayfrequency = 0;
2497         nt_devmode->reserved1        = 0;
2498         nt_devmode->reserved2        = 0;
2499         nt_devmode->panningwidth     = 0;
2500         nt_devmode->panningheight    = 0;
2501         
2502         nt_devmode->nt_dev_private = NULL;
2503         return nt_devmode;
2504 }
2505
2506 /****************************************************************************
2507  Deepcopy an NT devicemode.
2508 ****************************************************************************/
2509
2510 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2511 {
2512         NT_DEVICEMODE *new_nt_devicemode = NULL;
2513
2514         if ( !nt_devicemode )
2515                 return NULL;
2516
2517         if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2518                 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2519                 return NULL;
2520         }
2521
2522         new_nt_devicemode->nt_dev_private = NULL;
2523         if (nt_devicemode->nt_dev_private != NULL) {
2524                 if ((new_nt_devicemode->nt_dev_private = memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2525                         SAFE_FREE(new_nt_devicemode);
2526                         DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2527                         return NULL;
2528         }
2529         }
2530
2531         return new_nt_devicemode;
2532 }
2533
2534 /****************************************************************************
2535  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2536 ****************************************************************************/
2537
2538 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2539 {
2540         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2541
2542         if(nt_devmode == NULL)
2543                 return;
2544
2545         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2546
2547         SAFE_FREE(nt_devmode->nt_dev_private);
2548         SAFE_FREE(*devmode_ptr);
2549 }
2550
2551 /****************************************************************************
2552  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2553 ****************************************************************************/
2554
2555 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2556 {
2557         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2558
2559         if ( !info )
2560                 return;
2561
2562         free_nt_devicemode(&info->devmode);
2563
2564         TALLOC_FREE( *info_ptr );
2565 }
2566
2567
2568 /****************************************************************************
2569 ****************************************************************************/
2570 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2571 {
2572         int len = 0;
2573         int extra_len = 0;
2574         NT_DEVICEMODE devmode;
2575         
2576         ZERO_STRUCT(devmode);
2577
2578         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2579
2580         if (!*nt_devmode) return len;
2581
2582         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2583                           devmode.devicename,
2584                           devmode.formname,
2585
2586                           &devmode.specversion,
2587                           &devmode.driverversion,
2588                           &devmode.size,
2589                           &devmode.driverextra,
2590                           &devmode.orientation,
2591                           &devmode.papersize,
2592                           &devmode.paperlength,
2593                           &devmode.paperwidth,
2594                           &devmode.scale,
2595                           &devmode.copies,
2596                           &devmode.defaultsource,
2597                           &devmode.printquality,
2598                           &devmode.color,
2599                           &devmode.duplex,
2600                           &devmode.yresolution,
2601                           &devmode.ttoption,
2602                           &devmode.collate,
2603                           &devmode.logpixels,
2604                         
2605                           &devmode.fields,
2606                           &devmode.bitsperpel,
2607                           &devmode.pelswidth,
2608                           &devmode.pelsheight,
2609                           &devmode.displayflags,
2610                           &devmode.displayfrequency,
2611                           &devmode.icmmethod,
2612                           &devmode.icmintent,
2613                           &devmode.mediatype,
2614                           &devmode.dithertype,
2615                           &devmode.reserved1,
2616                           &devmode.reserved2,
2617                           &devmode.panningwidth,
2618                           &devmode.panningheight,
2619                           &devmode.nt_dev_private);
2620         
2621         if (devmode.nt_dev_private) {
2622                 /* the len in tdb_unpack is an int value and
2623                  * devmode.driverextra is only a short
2624                  */
2625                 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2626                 devmode.driverextra=(uint16)extra_len;
2627                 
2628                 /* check to catch an invalid TDB entry so we don't segfault */
2629                 if (devmode.driverextra == 0) {
2630                         devmode.nt_dev_private = NULL;
2631                 }
2632         }
2633
2634         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2635
2636         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2637         if (devmode.nt_dev_private)
2638                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2639
2640         return len;
2641 }
2642
2643 /****************************************************************************
2644  Allocate and initialize a new slot.
2645 ***************************************************************************/
2646  
2647 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2648 {
2649         NT_PRINTER_KEY  *d;
2650         int             key_index;
2651         
2652         if ( !name || !data )
2653                 return -1;
2654
2655         /* allocate another slot in the NT_PRINTER_KEY array */
2656         
2657         if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2658                 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2659                 return -1;
2660         }
2661
2662         data->keys = d;
2663         
2664         key_index = data->num_keys;
2665         
2666         /* initialze new key */
2667         
2668         data->keys[key_index].name = talloc_strdup( data, name );
2669         
2670         if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) ) 
2671                 return -1;
2672         
2673         data->num_keys++;
2674
2675         DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2676         
2677         return key_index;
2678 }
2679
2680 /****************************************************************************
2681  search for a registry key name in the existing printer data
2682  ***************************************************************************/
2683
2684 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2685 {
2686         int i;
2687         
2688         for ( i=0; i<data->num_keys; i++ ) {
2689                 if ( strequal( data->keys[i].name, name ) ) {
2690                 
2691                         /* cleanup memory */
2692                         
2693                         TALLOC_FREE( data->keys[i].name );
2694                         TALLOC_FREE( data->keys[i].values );
2695                         
2696                         /* if not the end of the array, move remaining elements down one slot */
2697                         
2698                         data->num_keys--;
2699                         if ( data->num_keys && (i < data->num_keys) )
2700                                 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2701                                 
2702                         break;
2703                 }
2704         }
2705         
2706
2707         return data->num_keys;
2708 }
2709
2710 /****************************************************************************
2711  search for a registry key name in the existing printer data
2712  ***************************************************************************/
2713  
2714 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2715 {
2716         int             key_index = -1;
2717         int             i;
2718         
2719         if ( !data || !name )
2720                 return -1;
2721
2722         DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2723
2724         /* loop over all existing keys */
2725         
2726         for ( i=0; i<data->num_keys; i++ ) {
2727                 if ( strequal(data->keys[i].name, name) ) {
2728                         DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2729                         key_index = i;
2730                         break;
2731                 
2732                 }
2733         }
2734         
2735         return key_index;
2736 }
2737
2738 /****************************************************************************
2739  ***************************************************************************/
2740
2741 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2742 {
2743         int     i, j;
2744         int     key_len;
2745         int     num_subkeys = 0;
2746         char    *p;
2747         fstring *ptr, *subkeys_ptr = NULL;
2748         fstring subkeyname;
2749         
2750         if ( !data )
2751                 return 0;
2752
2753         if ( !key )
2754                 return -1;
2755
2756         /* special case of asking for the top level printer data registry key names */
2757
2758         if ( strlen(key) == 0 ) {
2759                 for ( i=0; i<data->num_keys; i++ ) {
2760                 
2761                         /* found a match, so allocate space and copy the name */
2762                         
2763                         if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2764                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 
2765                                         num_subkeys+1));
2766                                 SAFE_FREE( subkeys );
2767                                 return -1;
2768                         }
2769                         
2770                         subkeys_ptr = ptr;
2771                         fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2772                         num_subkeys++;
2773                 }
2774
2775                 goto done;
2776         }
2777                 
2778         /* asking for the subkeys of some key */
2779         /* subkey paths are stored in the key name using '\' as the delimiter */
2780
2781         for ( i=0; i<data->num_keys; i++ ) {
2782                 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2783                         
2784                         /* if we found the exact key, then break */
2785                         key_len = strlen( key );
2786                         if ( strlen(data->keys[i].name) == key_len )
2787                                 break;
2788                         
2789                         /* get subkey path */
2790
2791                         p = data->keys[i].name + key_len;
2792                         if ( *p == '\\' )
2793                                 p++;
2794                         fstrcpy( subkeyname, p );
2795                         if ( (p = strchr( subkeyname, '\\' )) )
2796                                 *p = '\0';
2797                         
2798                         /* don't add a key more than once */
2799                         
2800                         for ( j=0; j<num_subkeys; j++ ) {
2801                                 if ( strequal( subkeys_ptr[j], subkeyname ) )
2802                                         break;
2803                         }
2804                         
2805                         if ( j != num_subkeys )
2806                                 continue;
2807
2808                         /* found a match, so allocate space and copy the name */
2809                         
2810                         if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2811                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 
2812                                         num_subkeys+1));
2813                                 SAFE_FREE( subkeys );
2814                                 return 0;
2815                         }
2816                         
2817                         subkeys_ptr = ptr;
2818                         fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2819                         num_subkeys++;
2820                 }
2821                 
2822         }
2823         
2824         /* return error if the key was not found */
2825         
2826         if ( i == data->num_keys )
2827                 return -1;
2828         
2829 done:
2830         /* tag off the end */
2831         
2832         if (num_subkeys)
2833                 fstrcpy(subkeys_ptr[num_subkeys], "" );
2834         
2835         *subkeys = subkeys_ptr;
2836
2837         return num_subkeys;
2838 }
2839
2840 #ifdef HAVE_ADS
2841 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name, 
2842                             const char *sz)
2843 {
2844         smb_ucs2_t conv_str[1024];
2845         size_t str_size;
2846
2847         regval_ctr_delvalue(ctr, val_name);
2848         str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2849                              STR_TERMINATE | STR_NOALIGN);
2850         regval_ctr_addvalue(ctr, val_name, REG_SZ, 
2851                             (char *) conv_str, str_size);
2852 }
2853
2854 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name, 
2855                                uint32 dword)
2856 {
2857         regval_ctr_delvalue(ctr, val_name);
2858         regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2859                             (char *) &dword, sizeof(dword));
2860 }
2861
2862 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2863                               BOOL b)
2864 {
2865         uint8 bin_bool = (b ? 1 : 0);
2866         regval_ctr_delvalue(ctr, val_name);
2867         regval_ctr_addvalue(ctr, val_name, REG_BINARY, 
2868                             (char *) &bin_bool, sizeof(bin_bool));
2869 }
2870
2871 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2872                                          const char *multi_sz)
2873 {
2874         smb_ucs2_t *conv_strs = NULL;
2875         size_t str_size;
2876
2877         /* a multi-sz has to have a null string terminator, i.e., the last
2878            string must be followed by two nulls */
2879         str_size = strlen(multi_sz) + 2;
2880         conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2881         if (!conv_strs) {
2882                 return;
2883         }
2884
2885         /* Change to byte units. */
2886         str_size *= sizeof(smb_ucs2_t);
2887         push_ucs2(NULL, conv_strs, multi_sz, str_size, 
2888                   STR_TERMINATE | STR_NOALIGN);
2889
2890         regval_ctr_delvalue(ctr, val_name);
2891         regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ, 
2892                             (char *) conv_strs, str_size);      
2893         safe_free(conv_strs);
2894         
2895 }
2896
2897 /****************************************************************************
2898  * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2899  *
2900  * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2901  * @return BOOL indicating success or failure
2902  ***************************************************************************/
2903
2904 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2905 {
2906         REGVAL_CTR *ctr = NULL;
2907         fstring longname;
2908         fstring dnssuffix;
2909         char *allocated_string = NULL;
2910         const char *ascii_str;
2911         int i;
2912
2913         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2914                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2915         ctr = info2->data->keys[i].values;
2916
2917         map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2918         map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2919
2920         /* we make the assumption that the netbios name is the same 
2921            as the DNS name sinc ethe former will be what we used to 
2922            join the domain */
2923
2924         if ( get_mydnsdomname( dnssuffix ) )
2925                 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2926         else
2927                 fstrcpy( longname, global_myname() );
2928                 
2929         map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2930
2931         asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2932         map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2933         SAFE_FREE(allocated_string);
2934
2935         map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2936         map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2937         map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2938         map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2939         map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2940         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2941         map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2942         map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2943         map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2944
2945         map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2946                           (info2->attributes & 
2947                            PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2948
2949         switch (info2->attributes & 0x3) {
2950         case 0:
2951                 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2952                 break;
2953         case 1:
2954                 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2955                 break;
2956         case 2:
2957                 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2958                 break;
2959         default:
2960                 ascii_str = "unknown";
2961         }
2962         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2963
2964         return True;
2965 }
2966
2967 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2, 
2968                                struct uuid guid)
2969 {
2970         int i;
2971         REGVAL_CTR *ctr=NULL;
2972
2973         /* find the DsSpooler key */
2974         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2975                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2976         ctr = info2->data->keys[i].values;
2977
2978         regval_ctr_delvalue(ctr, "objectGUID");
2979         regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY, 
2980                             (char *) &guid, sizeof(struct uuid));       
2981 }
2982
2983 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2984                                      NT_PRINTER_INFO_LEVEL *printer)
2985 {
2986         ADS_STATUS ads_rc;
2987         void *res;
2988         char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2989         char *srv_dn_utf8, **srv_cn_utf8;
2990         TALLOC_CTX *ctx;
2991         ADS_MODLIST mods;
2992         const char *attrs[] = {"objectGUID", NULL};
2993         struct uuid guid;
2994         WERROR win_rc = WERR_OK;
2995
2996         DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
2997
2998         /* figure out where to publish */
2999         ads_find_machine_acct(ads, &res, global_myname());
3000
3001         /* We use ldap_get_dn here as we need the answer
3002          * in utf8 to call ldap_explode_dn(). JRA. */
3003
3004         srv_dn_utf8 = ldap_get_dn(ads->ld, res);
3005         if (!srv_dn_utf8) {
3006                 ads_destroy(&ads);
3007                 return WERR_SERVER_UNAVAILABLE;
3008         }
3009         ads_msgfree(ads, res);
3010         srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3011         if (!srv_cn_utf8) {
3012                 ldap_memfree(srv_dn_utf8);
3013                 ads_destroy(&ads);
3014                 return WERR_SERVER_UNAVAILABLE;
3015         }
3016         /* Now convert to CH_UNIX. */
3017         if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
3018                 ldap_memfree(srv_dn_utf8);
3019                 ldap_memfree(srv_cn_utf8);
3020                 ads_destroy(&ads);
3021                 return WERR_SERVER_UNAVAILABLE;
3022         }
3023         if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
3024                 ldap_memfree(srv_dn_utf8);
3025                 ldap_memfree(srv_cn_utf8);
3026                 ads_destroy(&ads);
3027                 SAFE_FREE(srv_dn);
3028                 return WERR_SERVER_UNAVAILABLE;
3029         }
3030
3031         ldap_memfree(srv_dn_utf8);
3032         ldap_memfree(srv_cn_utf8);
3033
3034         asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0, 
3035                  printer->info_2->sharename, srv_dn);
3036
3037         SAFE_FREE(srv_dn);
3038         SAFE_FREE(srv_cn_0);
3039
3040         /* build the ads mods */
3041         ctx = talloc_init("nt_printer_publish_ads");
3042         mods = ads_init_mods(ctx);
3043
3044         get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3045         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, 
3046                     printer->info_2->sharename);
3047
3048         /* publish it */
3049         ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3050         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
3051                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3052
3053         if (!ADS_ERR_OK(ads_rc))
3054                 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3055         
3056         talloc_destroy(ctx);
3057
3058         /* retreive the guid and store it locally */
3059         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3060                 ZERO_STRUCT(guid);
3061                 ads_pull_guid(ads, res, &guid);
3062                 ads_msgfree(ads, res);
3063                 store_printer_guid(printer->info_2, guid);
3064                 win_rc = mod_a_printer(printer, 2);
3065         } 
3066
3067         SAFE_FREE(prt_dn);
3068         return win_rc;
3069 }
3070
3071 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3072                                        NT_PRINTER_INFO_LEVEL *printer)
3073 {
3074         ADS_STATUS ads_rc;
3075         void *res;
3076         char *prt_dn = NULL;
3077
3078         DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3079
3080         /* remove the printer from the directory */
3081         ads_rc = ads_find_printer_on_server(ads, &res, 
3082                             printer->info_2->sharename, global_myname());
3083
3084         if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
3085                 prt_dn = ads_get_dn(ads, res);
3086                 ads_rc = ads_del_dn(ads, prt_dn);
3087                 ads_memfree(ads, prt_dn);
3088         }
3089
3090         ads_msgfree(ads, res);
3091         return WERR_OK;
3092 }
3093
3094 /****************************************************************************
3095  * Publish a printer in the directory
3096  *
3097  * @param snum describing printer service
3098  * @return WERROR indicating status of publishing
3099  ***************************************************************************/
3100
3101 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3102 {
3103         ADS_STATUS ads_rc;
3104         ADS_STRUCT *ads = NULL;
3105         NT_PRINTER_INFO_LEVEL *printer = NULL;
3106         WERROR win_rc;
3107
3108         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3109         if (!W_ERROR_IS_OK(win_rc))
3110                 goto done;
3111
3112         switch (action) {
3113         case SPOOL_DS_PUBLISH:
3114         case SPOOL_DS_UPDATE:
3115                 /* set the DsSpooler info and attributes */
3116                 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3117                         win_rc = WERR_NOMEM;
3118                         goto done;
3119                 }
3120
3121                 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3122                 break;
3123         case SPOOL_DS_UNPUBLISH:
3124                 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3125                 break;
3126         default:
3127                 win_rc = WERR_NOT_SUPPORTED;
3128                 goto done;
3129         }
3130
3131         win_rc = mod_a_printer(printer, 2);
3132         if (!W_ERROR_IS_OK(win_rc)) {
3133                 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3134                 goto done;
3135         }
3136
3137         ads = ads_init(NULL, NULL, NULL);
3138         if (!ads) {
3139                 DEBUG(3, ("ads_init() failed\n"));
3140                 win_rc = WERR_SERVER_UNAVAILABLE;
3141                 goto done;
3142         }
3143         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3144         SAFE_FREE(ads->auth.password);
3145         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3146                 NULL, NULL);
3147
3148         /* ads_connect() will find the DC for us */                                         
3149         ads_rc = ads_connect(ads);
3150         if (!ADS_ERR_OK(ads_rc)) {
3151                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3152                 win_rc = WERR_ACCESS_DENIED;
3153                 goto done;
3154         }
3155
3156         switch (action) {
3157         case SPOOL_DS_PUBLISH:
3158         case SPOOL_DS_UPDATE:
3159                 win_rc = nt_printer_publish_ads(ads, printer);
3160                 break;
3161         case SPOOL_DS_UNPUBLISH:
3162                 win_rc = nt_printer_unpublish_ads(ads, printer);
3163                 break;
3164         }
3165
3166 done:
3167         free_a_printer(&printer, 2);
3168         ads_destroy(&ads);
3169         return win_rc;
3170 }
3171
3172 WERROR check_published_printers(void)
3173 {
3174         ADS_STATUS ads_rc;
3175         ADS_STRUCT *ads = NULL;
3176         int snum;
3177         int n_services = lp_numservices();
3178         NT_PRINTER_INFO_LEVEL *printer = NULL;
3179
3180         ads = ads_init(NULL, NULL, NULL);
3181         if (!ads) {
3182                 DEBUG(3, ("ads_init() failed\n"));
3183                 return WERR_SERVER_UNAVAILABLE;
3184         }
3185         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3186         SAFE_FREE(ads->auth.password);
3187         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3188                 NULL, NULL);
3189
3190         /* ads_connect() will find the DC for us */                                         
3191         ads_rc = ads_connect(ads);
3192         if (!ADS_ERR_OK(ads_rc)) {
3193                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3194                 ads_destroy(&ads);
3195                 return WERR_ACCESS_DENIED;
3196         }
3197
3198         for (snum = 0; snum < n_services; snum++) {
3199                 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3200                         continue;
3201
3202                 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3203                                                 lp_servicename(snum))) &&
3204                     (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3205                         nt_printer_publish_ads(ads, printer);
3206
3207                 free_a_printer(&printer, 2);
3208         }
3209
3210         ads_destroy(&ads);
3211         return WERR_OK;
3212 }
3213
3214 BOOL is_printer_published(Printer_entry *print_hnd, int snum, 
3215                           struct uuid *guid)
3216 {
3217         NT_PRINTER_INFO_LEVEL *printer = NULL;
3218         REGVAL_CTR *ctr;
3219         REGISTRY_VALUE *guid_val;
3220         WERROR win_rc;
3221         int i;
3222
3223         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3224
3225         if (!W_ERROR_IS_OK(win_rc) ||
3226             !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3227             ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3228             !(ctr = printer->info_2->data->keys[i].values) ||
3229             !(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) 
3230         {
3231                 free_a_printer(&printer, 2);
3232                 return False;
3233         }
3234
3235         /* fetching printer guids really ought to be a separate function.. */
3236         if (guid && regval_size(guid_val) == sizeof(struct uuid))
3237                 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
3238
3239         free_a_printer(&printer, 2);
3240         return True;
3241 }
3242 #else
3243 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3244 {
3245         return WERR_OK;
3246 }
3247
3248 WERROR check_published_printers(void)
3249 {
3250         return WERR_OK;
3251 }
3252
3253 BOOL is_printer_published(Printer_entry *print_hnd, int snum, 
3254                           struct uuid *guid)
3255 {
3256         return False;
3257 }
3258 #endif /* HAVE_ADS */
3259
3260 /****************************************************************************
3261  ***************************************************************************/
3262  
3263 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3264 {
3265         NT_PRINTER_DATA *data;
3266         int             i;
3267         int             removed_keys = 0;
3268         int             empty_slot;
3269         
3270         data = p2->data;
3271         empty_slot = data->num_keys;
3272
3273         if ( !key )
3274                 return WERR_INVALID_PARAM;
3275         
3276         /* remove all keys */
3277
3278         if ( !strlen(key) ) {
3279         
3280                 TALLOC_FREE( data );
3281
3282                 p2->data = NULL;
3283
3284                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3285                         p2->printername ));
3286         
3287                 return WERR_OK;
3288         }
3289
3290         /* remove a specific key (and all subkeys) */
3291         
3292         for ( i=0; i<data->num_keys; i++ ) {
3293                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3294                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3295                                 data->keys[i].name));
3296                 
3297                         TALLOC_FREE( data->keys[i].name );
3298                         TALLOC_FREE( data->keys[i].values );
3299
3300                         /* mark the slot as empty */
3301
3302                         ZERO_STRUCTP( &data->keys[i] );
3303                 }
3304         }
3305
3306         /* find the first empty slot */
3307
3308         for ( i=0; i<data->num_keys; i++ ) {
3309                 if ( !data->keys[i].name ) {
3310                         empty_slot = i;
3311                         removed_keys++;
3312                         break;
3313                 }
3314         }
3315
3316         if ( i == data->num_keys )
3317                 /* nothing was removed */
3318                 return WERR_INVALID_PARAM;
3319
3320         /* move everything down */
3321         
3322         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3323                 if ( data->keys[i].name ) {
3324                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) ); 
3325                         ZERO_STRUCTP( &data->keys[i] );
3326                         empty_slot++;
3327                         removed_keys++;
3328                 }
3329         }
3330
3331         /* update count */
3332                 
3333         data->num_keys -= removed_keys;
3334
3335         /* sanity check to see if anything is left */
3336
3337         if ( !data->num_keys ) {
3338                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3339
3340                 SAFE_FREE( data->keys );
3341                 ZERO_STRUCTP( data );
3342         }
3343
3344         return WERR_OK;
3345 }
3346
3347 /****************************************************************************
3348  ***************************************************************************/
3349  
3350 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3351 {
3352         WERROR          result = WERR_OK;
3353         int             key_index;
3354         
3355         /* we must have names on non-zero length */
3356         
3357         if ( !key || !*key|| !value || !*value )
3358                 return WERR_INVALID_NAME;
3359                 
3360         /* find the printer key first */
3361
3362         key_index = lookup_printerkey( p2->data, key );
3363         if ( key_index == -1 )
3364                 return WERR_OK;
3365         
3366         /* make sure the value exists so we can return the correct error code */
3367         
3368         if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3369                 return WERR_BADFILE;
3370                 
3371         regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3372         
3373         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3374                 key, value ));
3375         
3376         return result;
3377 }
3378
3379 /****************************************************************************
3380  ***************************************************************************/
3381  
3382 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value, 
3383                            uint32 type, uint8 *data, int real_len )
3384 {
3385         WERROR          result = WERR_OK;
3386         int             key_index;
3387
3388         /* we must have names on non-zero length */
3389         
3390         if ( !key || !*key|| !value || !*value )
3391                 return WERR_INVALID_NAME;
3392                 
3393         /* find the printer key first */
3394         
3395         key_index = lookup_printerkey( p2->data, key );
3396         if ( key_index == -1 )
3397                 key_index = add_new_printer_key( p2->data, key );
3398                 
3399         if ( key_index == -1 )
3400                 return WERR_NOMEM;
3401         
3402         regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3403                 type, (const char *)data, real_len );
3404         
3405         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3406                 key, value, type, real_len  ));
3407         
3408         return result;
3409 }
3410
3411 /****************************************************************************
3412  ***************************************************************************/
3413  
3414 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3415 {
3416         int             key_index;
3417
3418         if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3419                 return NULL;
3420
3421         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3422                 key, value ));
3423
3424         return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3425 }
3426
3427 /****************************************************************************
3428  Unpack a list of registry values frem the TDB
3429  ***************************************************************************/
3430  
3431 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3432 {
3433         int             len = 0;
3434         uint32          type;
3435         pstring         string, valuename, keyname;
3436         char            *str;
3437         int             size;
3438         uint8           *data_p;
3439         REGISTRY_VALUE  *regval_p;
3440         int             key_index;
3441
3442         /* add the "PrinterDriverData" key first for performance reasons */
3443         
3444         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3445
3446         /* loop and unpack the rest of the registry values */
3447         
3448         while ( True ) {
3449         
3450                 /* check to see if there are any more registry values */
3451                 
3452                 regval_p = NULL;
3453                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);         
3454                 if ( !regval_p ) 
3455                         break;
3456
3457                 /* unpack the next regval */
3458                 
3459                 len += tdb_unpack(buf+len, buflen-len, "fdB",
3460                                   string,
3461                                   &type,
3462                                   &size,
3463                                   &data_p);
3464
3465                 /* lookup for subkey names which have a type of REG_NONE */
3466                 /* there's no data with this entry */
3467
3468                 if ( type == REG_NONE ) {
3469                         if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3470                                 add_new_printer_key( printer_data, string );
3471                         continue;
3472                 }
3473         
3474                 /*
3475                  * break of the keyname from the value name.  
3476                  * Valuenames can have embedded '\'s so be careful.
3477                  * only support one level of keys.  See the 
3478                  * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3479                  * -- jerry
3480                  */     
3481                  
3482                 str = strchr_m( string, '\\');
3483                 
3484                 /* Put in "PrinterDriverData" is no key specified */
3485                 
3486                 if ( !str ) {
3487                         pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3488                         pstrcpy( valuename, string );
3489                 }
3490                 else {
3491                         *str = '\0';
3492                         pstrcpy( keyname, string );
3493                         pstrcpy( valuename, str+1 );
3494                 }
3495                         
3496                 /* see if we need a new key */
3497                 
3498                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3499                         key_index = add_new_printer_key( printer_data, keyname );
3500                         
3501                 if ( key_index == -1 ) {
3502                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3503                                 keyname));
3504                         break;
3505                 }
3506                 
3507                 /* add the new value */
3508                 
3509                 regval_ctr_addvalue( printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3510
3511                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3512
3513                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3514         }
3515
3516         return len;
3517 }
3518
3519 /****************************************************************************
3520  ***************************************************************************/
3521
3522 static void map_to_os2_driver(fstring drivername)
3523 {
3524         static BOOL initialised=False;
3525         static fstring last_from,last_to;
3526         char *mapfile = lp_os2_driver_map();
3527         char **lines = NULL;
3528         int numlines = 0;
3529         int i;
3530
3531         if (!strlen(drivername))
3532                 return;
3533
3534         if (!*mapfile)
3535                 return;
3536
3537         if (!initialised) {
3538                 *last_from = *last_to = 0;
3539                 initialised = True;
3540         }
3541
3542         if (strequal(drivername,last_from)) {
3543                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3544                 fstrcpy(drivername,last_to);
3545                 return;
3546         }
3547
3548         lines = file_lines_load(mapfile, &numlines);
3549         if (numlines == 0) {
3550                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3551                 return;
3552         }
3553
3554         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3555
3556         for( i = 0; i < numlines; i++) {
3557                 char *nt_name = lines[i];
3558                 char *os2_name = strchr(nt_name,'=');
3559
3560                 if (!os2_name)
3561                         continue;
3562
3563                 *os2_name++ = 0;
3564
3565                 while (isspace(*nt_name))
3566                         nt_name++;
3567
3568                 if (!*nt_name || strchr("#;",*nt_name))
3569                         continue;
3570
3571                 {
3572                         int l = strlen(nt_name);
3573                         while (l && isspace(nt_name[l-1])) {
3574                                 nt_name[l-1] = 0;
3575                                 l--;
3576                         }
3577                 }
3578
3579                 while (isspace(*os2_name))
3580                         os2_name++;
3581
3582                 {
3583                         int l = strlen(os2_name);
3584                         while (l && isspace(os2_name[l-1])) {
3585                                 os2_name[l-1] = 0;
3586                                 l--;
3587                         }
3588                 }
3589
3590                 if (strequal(nt_name,drivername)) {
3591                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3592                         fstrcpy(last_from,drivername);
3593                         fstrcpy(last_to,os2_name);
3594                         fstrcpy(drivername,os2_name);
3595                         file_lines_free(lines);
3596                         return;
3597                 }
3598         }
3599
3600         file_lines_free(lines);
3601 }
3602
3603 /****************************************************************************
3604  Get a default printer info 2 struct.
3605 ****************************************************************************/
3606 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
3607 {
3608         int snum;
3609
3610         snum = lp_servicenumber(sharename);
3611
3612         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3613         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s", 
3614                 servername, sharename);
3615         fstrcpy(info->sharename, sharename);
3616         fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3617
3618         /* by setting the driver name to an empty string, a local NT admin
3619            can now run the **local** APW to install a local printer driver
3620            for a Samba shared printer in 2.2.  Without this, drivers **must** be 
3621            installed on the Samba server for NT clients --jerry */
3622 #if 0   /* JERRY --do not uncomment-- */
3623         if (!*info->drivername)
3624                 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3625 #endif
3626
3627
3628         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3629
3630         pstrcpy(info->comment, "");
3631         fstrcpy(info->printprocessor, "winprint");
3632         fstrcpy(info->datatype, "RAW");
3633
3634         info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3635
3636         info->starttime = 0; /* Minutes since 12:00am GMT */
3637         info->untiltime = 0; /* Minutes since 12:00am GMT */
3638         info->priority = 1;
3639         info->default_priority = 1;
3640         info->setuptime = (uint32)time(NULL);
3641
3642         /*
3643          * I changed this as I think it is better to have a generic
3644          * DEVMODE than to crash Win2k explorer.exe   --jerry
3645          * See the HP Deskjet 990c Win2k drivers for an example.
3646          *
3647          * However the default devmode appears to cause problems
3648          * with the HP CLJ 8500 PCL driver.  Hence the addition of
3649          * the "default devmode" parameter   --jerry 22/01/2002
3650          */
3651
3652         if (lp_default_devmode(snum)) {
3653                 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL)
3654                         goto fail;
3655         }
3656         else {
3657                 info->devmode = NULL;
3658         }
3659
3660         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf))
3661                 goto fail;
3662
3663         return WERR_OK;
3664
3665 fail:
3666         if (info->devmode)
3667                 free_nt_devicemode(&info->devmode);
3668
3669         return WERR_ACCESS_DENIED;
3670 }
3671
3672 /****************************************************************************
3673 ****************************************************************************/
3674 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
3675 {
3676         int len = 0;
3677         int snum = lp_servicenumber(sharename);
3678         TDB_DATA kbuf, dbuf;
3679         fstring printername;
3680         char adevice[MAXDEVICENAME];
3681                 
3682         kbuf = make_printer_tdbkey( sharename );
3683
3684         dbuf = tdb_fetch(tdb_printers, kbuf);
3685         if (!dbuf.dptr)
3686                 return get_a_printer_2_default(info, servername, sharename);
3687
3688         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3689                         &info->attributes,
3690                         &info->priority,
3691                         &info->default_priority,
3692                         &info->starttime,
3693                         &info->untiltime,
3694                         &info->status,
3695                         &info->cjobs,
3696                         &info->averageppm,
3697                         &info->changeid,
3698                         &info->c_setprinter,
3699                         &info->setuptime,
3700                         info->servername,
3701                         info->printername,
3702                         info->sharename,
3703                         info->portname,
3704                         info->drivername,
3705                         info->comment,
3706                         info->location,
3707                         info->sepfile,
3708                         info->printprocessor,
3709                         info->datatype,
3710                         info->parameters);
3711
3712         /* Samba has to have shared raw drivers. */
3713         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3714         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3715
3716         /* Restore the stripped strings. */
3717         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3718
3719         if ( lp_force_printername(snum) )
3720                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3721         else 
3722                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3723
3724         fstrcpy(info->printername, printername);
3725
3726         len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
3727
3728         /*
3729          * Some client drivers freak out if there is a NULL devmode
3730          * (probably the driver is not checking before accessing 
3731          * the devmode pointer)   --jerry
3732          *
3733          * See comments in get_a_printer_2_default()
3734          */
3735
3736         if (lp_default_devmode(snum) && !info->devmode) {
3737                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3738                         printername));
3739                 info->devmode = construct_nt_devicemode(printername);
3740         }
3741
3742         slprintf( adevice, sizeof(adevice), "%s", info->printername );
3743         if (info->devmode) {
3744                 fstrcpy(info->devmode->devicename, adevice);    
3745         }
3746
3747         if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
3748                 DEBUG(0,("unpack_values: talloc() failed!\n"));
3749                 return WERR_NOMEM;
3750         }
3751         len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
3752
3753         /* This will get the current RPC talloc context, but we should be
3754            passing this as a parameter... fixme... JRA ! */
3755
3756         nt_printing_getsec(info, sharename, &info->secdesc_buf);
3757
3758         /* Fix for OS/2 drivers. */
3759
3760         if (get_remote_arch() == RA_OS2)
3761                 map_to_os2_driver(info->drivername);
3762
3763         SAFE_FREE(dbuf.dptr);
3764
3765         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3766                  sharename, info->printername, info->drivername));
3767
3768         return WERR_OK; 
3769 }
3770
3771 /****************************************************************************
3772  Debugging function, dump at level 6 the struct in the logs.
3773 ****************************************************************************/
3774 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3775 {
3776         uint32 result;
3777         NT_PRINTER_INFO_LEVEL_2 *info2;
3778         
3779         DEBUG(106,("Dumping printer at level [%d]\n", level));
3780         
3781         switch (level) {
3782                 case 2:
3783                 {
3784                         if (printer->info_2 == NULL)
3785                                 result=5;
3786                         else
3787                         {
3788                                 info2=printer->info_2;
3789                         
3790                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3791                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3792                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3793                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3794                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3795                                 DEBUGADD(106,("status:[%d]\n", info2->status));
3796                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3797                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3798                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3799                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3800                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3801
3802                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3803                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3804                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3805                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3806                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3807                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3808                                 DEBUGADD(106,("location:[%s]\n", info2->location));
3809                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3810                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3811                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3812                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3813                                 result=0;
3814                         }
3815                         break;
3816                 }
3817                 default:
3818                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3819                         result=1;
3820                         break;
3821         }
3822         
3823         return result;
3824 }
3825
3826 /****************************************************************************
3827  Update the changeid time.
3828  This is SO NASTY as some drivers need this to change, others need it
3829  static. This value will change every second, and I must hope that this
3830  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3831  UTAH ! JRA.
3832 ****************************************************************************/
3833
3834 static uint32 rev_changeid(void)
3835 {
3836         struct timeval tv;
3837
3838         get_process_uptime(&tv);
3839
3840 #if 1   /* JERRY */
3841         /* Return changeid as msec since spooler restart */
3842         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3843 #else
3844         /*
3845          * This setting seems to work well but is too untested
3846          * to replace the above calculation.  Left in for experiementation
3847          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
3848          */
3849         return tv.tv_sec * 10 + tv.tv_usec / 100000;
3850 #endif
3851 }
3852
3853
3854 /*
3855  * The function below are the high level ones.
3856  * only those ones must be called from the spoolss code.
3857  * JFM.
3858  */
3859
3860 /****************************************************************************
3861  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3862 ****************************************************************************/
3863
3864 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3865 {
3866         WERROR result;
3867         
3868         dump_a_printer(printer, level); 
3869         
3870         switch (level) {
3871                 case 2:
3872                 {
3873                         /*
3874                          * Update the changestamp.  Emperical tests show that the
3875                          * ChangeID is always updated,but c_setprinter is  
3876                          *  global spooler variable (not per printer).
3877                          */
3878
3879                         /* ChangeID **must** be increasing over the lifetime
3880                            of client's spoolss service in order for the
3881                            client's cache to show updates */
3882
3883                         printer->info_2->changeid = rev_changeid();
3884
3885                         /*
3886                          * Because one day someone will ask:
3887                          * NT->NT       An admin connection to a remote
3888                          *              printer show changes imeediately in
3889                          *              the properities dialog
3890                          *      
3891                          *              A non-admin connection will only show the
3892                          *              changes after viewing the properites page
3893                          *              2 times.  Seems to be related to a
3894                          *              race condition in the client between the spooler
3895                          *              updating the local cache and the Explorer.exe GUI
3896                          *              actually displaying the properties.
3897                          *
3898                          *              This is fixed in Win2k.  admin/non-admin
3899                          *              connections both display changes immediately.
3900                          *
3901                          * 14/12/01     --jerry
3902                          */
3903
3904                         result=update_a_printer_2(printer->info_2);
3905                         
3906                         break;
3907                 }
3908                 default:
3909                         result=WERR_UNKNOWN_LEVEL;
3910                         break;
3911         }
3912         
3913         return result;
3914 }
3915
3916 /****************************************************************************
3917  Initialize printer devmode & data with previously saved driver init values.
3918 ****************************************************************************/
3919
3920 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3921 {
3922         int                     len = 0;
3923         pstring                 key;
3924         TDB_DATA                kbuf, dbuf;
3925         NT_PRINTER_INFO_LEVEL_2 info;
3926
3927
3928         ZERO_STRUCT(info);
3929
3930         /*
3931          * Delete any printer data 'values' already set. When called for driver
3932          * replace, there will generally be some, but during an add printer, there
3933          * should not be any (if there are delete them).
3934          */
3935          
3936         if ( info_ptr->data )
3937                 delete_all_printer_data( info_ptr, "" );
3938         
3939         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3940
3941         kbuf.dptr = key;
3942         kbuf.dsize = strlen(key)+1;
3943
3944         dbuf = tdb_fetch(tdb_drivers, kbuf);
3945         if (!dbuf.dptr) {
3946                 /*
3947                  * When changing to a driver that has no init info in the tdb, remove
3948                  * the previous drivers init info and leave the new on blank.
3949                  */
3950                 free_nt_devicemode(&info_ptr->devmode);
3951                 return False;
3952         }
3953         
3954         /*
3955          * Get the saved DEVMODE..
3956          */
3957          
3958         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3959
3960         /*
3961          * The saved DEVMODE contains the devicename from the printer used during
3962          * the initialization save. Change it to reflect the new printer.
3963          */
3964          
3965         if ( info.devmode ) {
3966                 ZERO_STRUCT(info.devmode->devicename);
3967                 fstrcpy(info.devmode->devicename, info_ptr->printername);
3968         }
3969
3970         /*
3971          * NT/2k does not change out the entire DeviceMode of a printer
3972          * when changing the driver.  Only the driverextra, private, & 
3973          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
3974          *
3975          * Later examination revealed that Windows NT/2k does reset the
3976          * the printer's device mode, bit **only** when you change a 
3977          * property of the device mode such as the page orientation.
3978          * --jerry
3979          */
3980
3981
3982         /* Bind the saved DEVMODE to the new the printer */
3983          
3984         free_nt_devicemode(&info_ptr->devmode);
3985         info_ptr->devmode = info.devmode;
3986
3987         DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3988                 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3989
3990         /* Add the printer data 'values' to the new printer */
3991
3992         if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
3993                 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
3994                 return False;
3995         }
3996          
3997         len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3998         
3999
4000         SAFE_FREE(dbuf.dptr);
4001
4002         return True;    
4003 }
4004
4005 /****************************************************************************
4006  Initialize printer devmode & data with previously saved driver init values.
4007  When a printer is created using AddPrinter, the drivername bound to the
4008  printer is used to lookup previously saved driver initialization info, which
4009  is bound to the new printer.
4010 ****************************************************************************/
4011
4012 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4013 {
4014         BOOL result = False;
4015         
4016         switch (level) {
4017                 case 2:
4018                         result = set_driver_init_2(printer->info_2);
4019                         break;
4020                         
4021                 default:
4022                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
4023                                 level));
4024                         break;
4025         }
4026         
4027         return result;
4028 }
4029
4030 /****************************************************************************
4031  Delete driver init data stored for a specified driver
4032 ****************************************************************************/
4033
4034 BOOL del_driver_init(char *drivername)
4035 {
4036         pstring key;
4037         TDB_DATA kbuf;
4038
4039         if (!drivername || !*drivername) {
4040                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4041                 return False;
4042         }
4043
4044         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
4045
4046         kbuf.dptr = key;
4047         kbuf.dsize = strlen(key)+1;
4048
4049         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
4050
4051         return (tdb_delete(tdb_drivers, kbuf) == 0);
4052 }
4053
4054 /****************************************************************************
4055  Pack up the DEVMODE and values for a printer into a 'driver init' entry 
4056  in the tdb. Note: this is different from the driver entry and the printer
4057  entry. There should be a single driver init entry for each driver regardless
4058  of whether it was installed from NT or 2K. Technically, they should be
4059  different, but they work out to the same struct.
4060 ****************************************************************************/
4061
4062 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4063 {
4064         pstring key;
4065         char *buf;
4066         int buflen, len, ret;
4067         TDB_DATA kbuf, dbuf;
4068
4069         buf = NULL;
4070         buflen = 0;
4071
4072  again: 
4073         len = 0;
4074         len += pack_devicemode(info->devmode, buf+len, buflen-len);
4075
4076         len += pack_values( info->data, buf+len, buflen-len );
4077
4078         if (buflen < len) {
4079                 char *tb;
4080
4081                 tb = (char *)SMB_REALLOC(buf, len);
4082                 if (!tb) {
4083                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4084                         ret = -1;
4085                         goto done;
4086                 }
4087                 else
4088                         buf = tb;
4089                 buflen = len;
4090                 goto again;
4091         }
4092
4093         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4094
4095         kbuf.dptr = key;
4096         kbuf.dsize = strlen(key)+1;
4097         dbuf.dptr = buf;
4098         dbuf.dsize = len;
4099
4100         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
4101
4102 done:
4103         if (ret == -1)
4104                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4105
4106         SAFE_FREE(buf);
4107
4108         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4109                  info->sharename, info->drivername));
4110
4111         return ret;
4112 }
4113
4114 /****************************************************************************
4115  Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4116 ****************************************************************************/
4117
4118 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4119 {
4120         uint32 result;
4121         
4122         dump_a_printer(printer, level); 
4123         
4124         switch (level) {
4125                 case 2:
4126                         result = update_driver_init_2(printer->info_2);
4127                         break;
4128                 default:
4129                         result = 1;
4130                         break;
4131         }
4132         
4133         return result;
4134 }
4135
4136 /****************************************************************************
4137  Convert the printer data value, a REG_BINARY array, into an initialization 
4138  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4139  got to keep the endians happy :).
4140 ****************************************************************************/
4141
4142 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4143 {
4144         BOOL       result = False;
4145         prs_struct ps;
4146         DEVICEMODE devmode;
4147
4148         ZERO_STRUCT(devmode);
4149
4150         prs_init(&ps, 0, ctx, UNMARSHALL);
4151         ps.data_p      = (char *)data;
4152         ps.buffer_size = data_len;
4153
4154         if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4155                 result = convert_devicemode("", &devmode, &nt_devmode);
4156         else
4157                 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4158
4159         return result;
4160 }
4161
4162 /****************************************************************************
4163  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4164
4165  1. Use the driver's config DLL to this UNC printername and:
4166     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4167     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4168  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4169
4170  The last step triggers saving the "driver initialization" information for
4171  this printer into the tdb. Later, new printers that use this driver will
4172  have this initialization information bound to them. This simulates the
4173  driver initialization, as if it had run on the Samba server (as it would
4174  have done on NT).
4175
4176  The Win32 client side code requirement sucks! But until we can run arbitrary
4177  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4178  
4179  It would have been easier to use SetPrinter because all the UNMARSHALLING of
4180  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4181  about it and you will realize why.  JRR 010720
4182 ****************************************************************************/
4183
4184 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4185 {
4186         WERROR        status       = WERR_OK;
4187         TALLOC_CTX    *ctx         = NULL;
4188         NT_DEVICEMODE *nt_devmode  = NULL;
4189         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4190         
4191         /*
4192          * When the DEVMODE is already set on the printer, don't try to unpack it.
4193          */
4194         DEBUG(8,("save_driver_init_2: Enter...\n"));
4195         
4196         if ( !printer->info_2->devmode && data_len ) {
4197                 /*
4198                  * Set devmode on printer info, so entire printer initialization can be
4199                  * saved to tdb.
4200                  */
4201
4202                 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4203                         return WERR_NOMEM;
4204
4205                 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4206                         status = WERR_NOMEM;
4207                         goto done;
4208                 }
4209         
4210                 ZERO_STRUCTP(nt_devmode);
4211
4212                 /*
4213                  * The DEVMODE is held in the 'data' component of the param in raw binary.
4214                  * Convert it to to a devmode structure
4215                  */
4216                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4217                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4218                         status = WERR_INVALID_PARAM;
4219                         goto done;
4220                 }
4221
4222                 printer->info_2->devmode = nt_devmode;
4223         }
4224
4225         /*
4226          * Pack up and add (or update) the DEVMODE and any current printer data to
4227          * a 'driver init' element in the tdb
4228          * 
4229          */
4230
4231         if ( update_driver_init(printer, 2) != 0 ) {
4232                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4233                 status = WERR_NOMEM;
4234                 goto done;
4235         }
4236         
4237         /*
4238          * If driver initialization info was successfully saved, set the current 
4239          * printer to match it. This allows initialization of the current printer 
4240          * as well as the driver.
4241          */
4242         status = mod_a_printer(printer, 2);
4243         if (!W_ERROR_IS_OK(status)) {
4244                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4245                                   printer->info_2->printername));
4246         }
4247         
4248   done:
4249         talloc_destroy(ctx);
4250         free_nt_devicemode( &nt_devmode );
4251         
4252         printer->info_2->devmode = tmp_devmode;
4253
4254         return status;
4255 }
4256
4257 /****************************************************************************
4258  Update the driver init info (DEVMODE and specifics) for a printer
4259 ****************************************************************************/
4260
4261 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4262 {
4263         WERROR status = WERR_OK;
4264         
4265         switch (level) {
4266                 case 2:
4267                         status = save_driver_init_2( printer, data, data_len );
4268                         break;
4269                 default:
4270                         status = WERR_UNKNOWN_LEVEL;
4271                         break;
4272         }
4273         
4274         return status;
4275 }
4276
4277 /****************************************************************************
4278  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4279
4280  Previously the code had a memory allocation problem because it always
4281  used the TALLOC_CTX from the Printer_entry*.   This context lasts 
4282  as a long as the original handle is open.  So if the client made a lot 
4283  of getprinter[data]() calls, the memory usage would climb.  Now we use
4284  a short lived TALLOC_CTX for printer_info_2 objects returned.  We 
4285  still use the Printer_entry->ctx for maintaining the cache copy though
4286  since that object must live as long as the handle by definition.  
4287                                                     --jerry
4288
4289 ****************************************************************************/
4290
4291 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, 
4292                         const char *sharename)
4293 {
4294         WERROR result;
4295         fstring servername;
4296         
4297         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4298
4299         if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4300                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4301                 return WERR_NOMEM;
4302         }
4303
4304         switch (level) {
4305                 case 2:
4306                         if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4307                                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4308                                 TALLOC_FREE( *pp_printer );
4309                                 return WERR_NOMEM;
4310                         }
4311
4312                         if ( print_hnd ) 
4313                                 fstrcpy( servername, print_hnd->servername );
4314                         else {
4315                                 fstrcpy( servername, "%L" );
4316                                 standard_sub_basic( "", servername, sizeof(servername)-1 );
4317                         }
4318
4319                         result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4320         
4321                         
4322                         /* we have a new printer now.  Save it with this handle */
4323                         
4324                         if ( !W_ERROR_IS_OK(result) ) {
4325                                 TALLOC_FREE( *pp_printer );
4326                                 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", 
4327                                         sharename, (unsigned int)level, dos_errstr(result)));
4328                                 return result;
4329                         }
4330
4331                         dump_a_printer( *pp_printer, level);
4332                         
4333                         break;
4334                         
4335                 default:
4336                         TALLOC_FREE( *pp_printer );
4337                         return WERR_UNKNOWN_LEVEL;
4338         }
4339         
4340         return WERR_OK;
4341 }
4342
4343 /****************************************************************************
4344  Deletes a NT_PRINTER_INFO_LEVEL struct.
4345 ****************************************************************************/
4346
4347 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4348 {
4349         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4350
4351         if ( !printer )
4352                 return 0;
4353         
4354         switch (level) {
4355                 case 2:
4356                         if ( printer->info_2 ) 
4357                                 free_nt_printer_info_level_2(&printer->info_2);
4358                         break;
4359
4360                 default:
4361                         DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4362                         return 1;
4363         }
4364
4365         TALLOC_FREE(*pp_printer);
4366
4367         return 0;
4368 }
4369
4370 /****************************************************************************
4371 ****************************************************************************/
4372 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4373 {
4374         uint32 result;
4375         DEBUG(104,("adding a printer at level [%d]\n", level));
4376         dump_a_printer_driver(driver, level);
4377         
4378         switch (level) {
4379                 case 3:
4380                         result=add_a_printer_driver_3(driver.info_3);
4381                         break;
4382
4383                 case 6:
4384                         result=add_a_printer_driver_6(driver.info_6);
4385                         break;
4386
4387                 default:
4388                         result=1;
4389                         break;
4390         }
4391         
4392         return result;
4393 }
4394 /****************************************************************************
4395 ****************************************************************************/
4396
4397 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4398                             fstring drivername, const char *architecture, uint32 version)
4399 {
4400         WERROR result;
4401         
4402         switch (level) {
4403                 case 3:
4404                         /* Sometime we just want any version of the driver */
4405                         
4406                         if ( version == DRIVER_ANY_VERSION ) {
4407                                 /* look for Win2k first and then for NT4 */
4408                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4409                                                 architecture, 3);
4410                                                 
4411                                 if ( !W_ERROR_IS_OK(result) ) {
4412                                         result = get_a_printer_driver_3( &driver->info_3, 
4413                                                         drivername, architecture, 2 );
4414                                 }
4415                         } else {
4416                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4417                                         architecture, version);                         
4418                         }
4419                         break;
4420                         
4421                 default:
4422                         result=W_ERROR(1);
4423                         break;
4424         }
4425         
4426         if (W_ERROR_IS_OK(result))
4427                 dump_a_printer_driver(*driver, level);
4428                 
4429         return result;
4430 }
4431
4432 /****************************************************************************
4433 ****************************************************************************/
4434 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4435 {
4436         uint32 result;
4437         
4438         switch (level) {
4439                 case 3:
4440                 {
4441                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4442                         if (driver.info_3 != NULL)
4443                         {
4444                                 info3=driver.info_3;
4445                                 SAFE_FREE(info3->dependentfiles);
4446                                 ZERO_STRUCTP(info3);
4447                                 SAFE_FREE(info3);
4448                                 result=0;
4449                         } else {
4450                                 result=4;
4451                         }
4452                         break;
4453                 }
4454                 case 6:
4455                 {
4456                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4457                         if (driver.info_6 != NULL) {
4458                                 info6=driver.info_6;
4459                                 SAFE_FREE(info6->dependentfiles);
4460                                 SAFE_FREE(info6->previousnames);
4461                                 ZERO_STRUCTP(info6);
4462                                 SAFE_FREE(info6);
4463                                 result=0;
4464                         } else {
4465                                 result=4;
4466                         }
4467                         break;
4468                 }
4469                 default:
4470                         result=1;
4471                         break;
4472         }
4473         return result;
4474 }
4475
4476
4477 /****************************************************************************
4478   Determine whether or not a particular driver is currently assigned
4479   to a printer
4480 ****************************************************************************/
4481
4482 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4483 {
4484         int snum;
4485         int n_services = lp_numservices();
4486         NT_PRINTER_INFO_LEVEL *printer = NULL;
4487         BOOL in_use = False;
4488
4489         if ( !info_3 ) 
4490                 return False;
4491
4492         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4493         
4494         /* loop through the printers.tdb and check for the drivername */
4495         
4496         for (snum=0; snum<n_services && !in_use; snum++) {
4497                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4498                         continue;
4499                 
4500                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4501                         continue;
4502                 
4503                 if ( strequal(info_3->name, printer->info_2->drivername) ) 
4504                         in_use = True;
4505                 
4506                 free_a_printer( &printer, 2 );
4507         }
4508         
4509         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4510         
4511         if ( in_use ) {
4512                 NT_PRINTER_DRIVER_INFO_LEVEL d;
4513                 WERROR werr;
4514                 
4515                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4516                 
4517                 /* we can still remove the driver if there is one of 
4518                    "Windows NT x86" version 2 or 3 left */
4519                    
4520                 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4521                         werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );                       
4522                 }
4523                 else {
4524                         switch ( info_3->cversion ) {
4525                         case 2:
4526                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4527                                 break;
4528                         case 3: 
4529                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4530                                 break;
4531                         default:
4532                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n", 
4533                                         info_3->cversion));
4534                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4535                                 break;
4536                         }
4537                 }
4538
4539                 /* now check the error code */
4540                                 
4541                 if ( W_ERROR_IS_OK(werr) ) {
4542                         /* it's ok to remove the driver, we have other architctures left */
4543                         in_use = False;
4544                         free_a_printer_driver( d, 3 );
4545                 }
4546         }
4547         
4548         /* report that the driver is not in use by default */
4549         
4550         return in_use;
4551 }
4552
4553
4554 /**********************************************************************
4555  Check to see if a ogiven file is in use by *info
4556  *********************************************************************/
4557  
4558 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4559 {
4560         int i = 0;
4561         
4562         if ( !info )
4563                 return False;
4564                 
4565         if ( strequal(file, info->driverpath) )
4566                 return True;
4567
4568         if ( strequal(file, info->datafile) )
4569                 return True;
4570
4571         if ( strequal(file, info->configfile) )
4572                 return True;
4573
4574         if ( strequal(file, info->helpfile) )
4575                 return True;
4576         
4577         /* see of there are any dependent files to examine */
4578         
4579         if ( !info->dependentfiles )
4580                 return False;
4581         
4582         while ( *info->dependentfiles[i] ) {
4583                 if ( strequal(file, info->dependentfiles[i]) )
4584                         return True;
4585                 i++;
4586         }
4587         
4588         return False;
4589
4590 }
4591
4592 /**********************************************************************
4593  Utility function to remove the dependent file pointed to by the 
4594  input parameter from the list 
4595  *********************************************************************/
4596
4597 static void trim_dependent_file( fstring files[], int idx )
4598 {
4599         
4600         /* bump everything down a slot */
4601
4602         while( *files[idx+1] ) {
4603                 fstrcpy( files[idx], files[idx+1] );
4604                 idx++;
4605         }
4606         
4607         *files[idx] = '\0';
4608
4609         return; 
4610 }
4611
4612 /**********************************************************************
4613  Check if any of the files used by src are also used by drv 
4614  *********************************************************************/
4615
4616 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, 
4617                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4618 {
4619         BOOL    in_use = False;
4620         int     i = 0;
4621         
4622         if ( !src || !drv )
4623                 return False;
4624                 
4625         /* check each file.  Remove it from the src structure if it overlaps */
4626         
4627         if ( drv_file_in_use(src->driverpath, drv) ) {
4628                 in_use = True;
4629                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4630                 fstrcpy( src->driverpath, "" );
4631         }
4632                 
4633         if ( drv_file_in_use(src->datafile, drv) ) {
4634                 in_use = True;
4635                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4636                 fstrcpy( src->datafile, "" );
4637         }
4638                 
4639         if ( drv_file_in_use(src->configfile, drv) ) {
4640                 in_use = True;
4641                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4642                 fstrcpy( src->configfile, "" );
4643         }
4644                 
4645         if ( drv_file_in_use(src->helpfile, drv) ) {
4646                 in_use = True;
4647                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4648                 fstrcpy( src->helpfile, "" );
4649         }
4650         
4651         /* are there any dependentfiles to examine? */
4652         
4653         if ( !src->dependentfiles )
4654                 return in_use;
4655                 
4656         while ( *src->dependentfiles[i] ) {
4657                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4658                         in_use = True;
4659                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4660                         trim_dependent_file( src->dependentfiles, i );
4661                 } else
4662                         i++;
4663         }               
4664                 
4665         return in_use;
4666 }
4667
4668 /****************************************************************************
4669   Determine whether or not a particular driver files are currently being 
4670   used by any other driver.  
4671   
4672   Return value is True if any files were in use by other drivers
4673   and False otherwise.
4674   
4675   Upon return, *info has been modified to only contain the driver files
4676   which are not in use
4677 ****************************************************************************/
4678
4679 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4680 {
4681         int                             i;
4682         int                             ndrivers;
4683         uint32                          version;
4684         fstring                         *list = NULL;
4685         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
4686         
4687         if ( !info )
4688                 return False;
4689         
4690         version = info->cversion;
4691         
4692         /* loop over all driver versions */
4693         
4694         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4695         
4696         /* get the list of drivers */
4697                 
4698         list = NULL;
4699         ndrivers = get_ntdrivers(&list, info->environment, version);
4700                 
4701         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
4702                 ndrivers, info->environment, version));
4703
4704         /* check each driver for overlap in files */
4705                 
4706         for (i=0; i<ndrivers; i++) {
4707                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4708                         
4709                 ZERO_STRUCT(driver);
4710                         
4711                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4712                         SAFE_FREE(list);
4713                         return True;
4714                 }
4715                         
4716                 /* check if d2 uses any files from d1 */
4717                 /* only if this is a different driver than the one being deleted */
4718                         
4719                 if ( !strequal(info->name, driver.info_3->name) ) {
4720                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
4721                                 free_a_printer_driver(driver, 3);
4722                                 SAFE_FREE( list );
4723                                 return True;
4724                         }
4725                 }
4726         
4727                 free_a_printer_driver(driver, 3);
4728         }       
4729         
4730         SAFE_FREE(list);
4731         
4732         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4733         
4734         driver.info_3 = info;
4735         
4736         if ( DEBUGLEVEL >= 20 )
4737                 dump_a_printer_driver( driver, 3 );
4738         
4739         return False;
4740 }
4741
4742 /****************************************************************************
4743   Actually delete the driver files.  Make sure that 
4744   printer_driver_files_in_use() return False before calling 
4745   this.
4746 ****************************************************************************/
4747
4748 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4749 {
4750         int i = 0;
4751         char *s;
4752         pstring file;
4753         connection_struct *conn;
4754         DATA_BLOB null_pw;
4755         NTSTATUS nt_status;
4756         fstring res_type;
4757         BOOL bad_path;
4758         SMB_STRUCT_STAT  st;
4759
4760         if ( !info_3 )
4761                 return False;
4762                 
4763         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4764         
4765         /*
4766          * Connect to the print$ share under the same account as the 
4767          * user connected to the rpc pipe. Note we must be root to 
4768          * do this.
4769          */
4770          
4771         null_pw = data_blob( NULL, 0 );
4772         fstrcpy(res_type, "A:");
4773         become_root();
4774         conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4775         unbecome_root();
4776         
4777         if ( !conn ) {
4778                 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4779                 return False;
4780         }
4781
4782         if ( !CAN_WRITE(conn) ) {
4783                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4784                 return False;
4785         }
4786
4787         /* Save who we are - we are temporarily becoming the connection user. */
4788
4789         if ( !become_user(conn, conn->vuid) ) {
4790                 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4791                 return False;
4792         }
4793
4794         /* now delete the files; must strip the '\print$' string from 
4795            fron of path                                                */
4796         
4797         if ( *info_3->driverpath ) {
4798                 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4799                         pstrcpy( file, s );
4800                         driver_unix_convert(file, conn, NULL, &bad_path, &st);
4801                         DEBUG(10,("deleting driverfile [%s]\n", s));
4802                         unlink_internals(conn, 0, file, False);
4803                 }
4804         }
4805                 
4806         if ( *info_3->configfile ) {
4807                 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4808                         pstrcpy( file, s );
4809                         driver_unix_convert(file, conn, NULL, &bad_path, &st);
4810                         DEBUG(10,("deleting configfile [%s]\n", s));
4811                         unlink_internals(conn, 0, file, False);
4812                 }
4813         }
4814         
4815         if ( *info_3->datafile ) {
4816                 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4817                         pstrcpy( file, s );
4818                         driver_unix_convert(file, conn, NULL, &bad_path, &st);
4819                         DEBUG(10,("deleting datafile [%s]\n", s));
4820                         unlink_internals(conn, 0, file, False);
4821                 }
4822         }
4823         
4824         if ( *info_3->helpfile ) {
4825                 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4826                         pstrcpy( file, s );
4827                         driver_unix_convert(file, conn, NULL, &bad_path, &st);
4828                         DEBUG(10,("deleting helpfile [%s]\n", s));
4829                         unlink_internals(conn, 0, file, False);
4830                 }
4831         }
4832         
4833         /* check if we are done removing files */
4834         
4835         if ( info_3->dependentfiles ) {
4836                 while ( info_3->dependentfiles[i][0] ) {
4837                         char *p;
4838
4839                         /* bypass the "\print$" portion of the path */
4840                         
4841                         if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4842                                 pstrcpy( file, p );
4843                                 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4844                                 DEBUG(10,("deleting dependent file [%s]\n", file));
4845                                 unlink_internals(conn, 0, file, False);
4846                         }
4847                         
4848                         i++;
4849                 }
4850         }
4851
4852         unbecome_user();
4853         
4854         return True;
4855 }
4856
4857 /****************************************************************************
4858  Remove a printer driver from the TDB.  This assumes that the the driver was
4859  previously looked up.
4860  ***************************************************************************/
4861
4862 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4863                               uint32 version, BOOL delete_files )
4864 {
4865         pstring         key;
4866         const char     *arch;
4867         TDB_DATA        kbuf, dbuf;
4868         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
4869
4870         /* delete the tdb data first */
4871
4872         arch = get_short_archi(info_3->environment);
4873         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4874                 arch, version, info_3->name);
4875
4876         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4877                 key, delete_files ? "TRUE" : "FALSE" ));
4878
4879         ctr.info_3 = info_3;
4880         dump_a_printer_driver( ctr, 3 );
4881
4882         kbuf.dptr=key;
4883         kbuf.dsize=strlen(key)+1;
4884
4885         /* check if the driver actually exists for this environment */
4886         
4887         dbuf = tdb_fetch( tdb_drivers, kbuf );
4888         if ( !dbuf.dptr ) {
4889                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4890                 return WERR_UNKNOWN_PRINTER_DRIVER;
4891         }
4892                 
4893         SAFE_FREE( dbuf.dptr );
4894         
4895         /* ok... the driver exists so the delete should return success */
4896                 
4897         if (tdb_delete(tdb_drivers, kbuf) == -1) {
4898                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4899                 return WERR_ACCESS_DENIED;
4900         }
4901
4902         /*
4903          * now delete any associated files if delete_files == True
4904          * even if this part failes, we return succes because the
4905          * driver doesn not exist any more
4906          */
4907
4908         if ( delete_files )
4909                 delete_driver_files( info_3, user );
4910                         
4911                 
4912         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4913
4914         return WERR_OK;
4915         }
4916         
4917 /****************************************************************************
4918  Store a security desc for a printer.
4919 ****************************************************************************/
4920
4921 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
4922 {
4923         SEC_DESC_BUF *new_secdesc_ctr = NULL;
4924         SEC_DESC_BUF *old_secdesc_ctr = NULL;
4925         prs_struct ps;
4926         TALLOC_CTX *mem_ctx = NULL;
4927         char *key;
4928         WERROR status;
4929
4930         mem_ctx = talloc_init("nt_printing_setsec");
4931         if (mem_ctx == NULL)
4932                 return WERR_NOMEM;
4933
4934         /* The old owner and group sids of the security descriptor are not
4935            present when new ACEs are added or removed by changing printer
4936            permissions through NT.  If they are NULL in the new security
4937            descriptor then copy them over from the old one. */
4938
4939         if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4940                 DOM_SID *owner_sid, *group_sid;
4941                 SEC_ACL *dacl, *sacl;
4942                 SEC_DESC *psd = NULL;
4943                 size_t size;
4944
4945                 nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr);
4946
4947                 /* Pick out correct owner and group sids */
4948
4949                 owner_sid = secdesc_ctr->sec->owner_sid ?
4950                         secdesc_ctr->sec->owner_sid :
4951                         old_secdesc_ctr->sec->owner_sid;
4952
4953                 group_sid = secdesc_ctr->sec->grp_sid ?
4954                         secdesc_ctr->sec->grp_sid :
4955                         old_secdesc_ctr->sec->grp_sid;
4956
4957                 dacl = secdesc_ctr->sec->dacl ?
4958                         secdesc_ctr->sec->dacl :
4959                         old_secdesc_ctr->sec->dacl;
4960
4961                 sacl = secdesc_ctr->sec->sacl ?
4962                         secdesc_ctr->sec->sacl :
4963                         old_secdesc_ctr->sec->sacl;
4964
4965                 /* Make a deep copy of the security descriptor */
4966
4967                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4968                                     owner_sid, group_sid,
4969                                     sacl,
4970                                     dacl,
4971                                     &size);
4972
4973                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4974         }
4975
4976         if (!new_secdesc_ctr) {
4977                 new_secdesc_ctr = secdesc_ctr;
4978         }
4979
4980         /* Store the security descriptor in a tdb */
4981
4982         prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4983                  sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4984
4985         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4986                              &ps, 1)) {
4987                 status = WERR_BADFUNC;
4988                 goto out;
4989         }
4990
4991         key = make_printers_secdesc_tdbkey( sharename );
4992
4993         if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4994                 status = WERR_OK;
4995         } else {
4996                 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
4997                 status = WERR_BADFUNC;
4998         }
4999
5000         /* Free malloc'ed memory */
5001
5002  out:
5003
5004         prs_mem_free(&ps);
5005         if (mem_ctx)
5006                 talloc_destroy(mem_ctx);
5007         return status;
5008 }
5009
5010 /****************************************************************************
5011  Construct a default security descriptor buffer for a printer.
5012 ****************************************************************************/
5013
5014 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5015 {
5016         SEC_ACE ace[5]; /* max number of ace entries */
5017         int i = 0;
5018         SEC_ACCESS sa;
5019         SEC_ACL *psa = NULL;
5020         SEC_DESC_BUF *sdb = NULL;
5021         SEC_DESC *psd = NULL;
5022         DOM_SID adm_sid;
5023         size_t sd_size;
5024
5025         /* Create an ACE where Everyone is allowed to print */
5026
5027         init_sec_access(&sa, PRINTER_ACE_PRINT);
5028         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5029                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5030
5031         /* Add the domain admins group if we are a DC */
5032         
5033         if ( IS_DC ) {
5034                 DOM_SID domadmins_sid;
5035                 
5036                 sid_copy(&domadmins_sid, get_global_sam_sid());
5037                 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5038                 
5039                 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5040                 init_sec_ace(&ace[i++], &domadmins_sid, 
5041                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5042                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5043                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5044                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5045         }
5046         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5047                 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5048
5049                 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5050                 init_sec_ace(&ace[i++], &adm_sid, 
5051                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5052                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5053                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5054                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5055         }
5056
5057         /* add BUILTIN\Administrators as FULL CONTROL */
5058
5059         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5060         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 
5061                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5062                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5063         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 
5064                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5065                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5066
5067         /* Make the security descriptor owned by the BUILTIN\Administrators */
5068
5069         /* The ACL revision number in rpc_secdesc.h differs from the one
5070            created by NT when setting ACE entries in printer
5071            descriptors.  NT4 complains about the property being edited by a
5072            NT5 machine. */
5073
5074         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5075                 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5076                         &global_sid_Builtin_Administrators, 
5077                         &global_sid_Builtin_Administrators,
5078                         NULL, psa, &sd_size);
5079         }
5080
5081         if (!psd) {
5082                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5083                 return NULL;
5084         }
5085
5086         sdb = make_sec_desc_buf(ctx, sd_size, psd);
5087
5088         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5089                  (unsigned int)sd_size));
5090
5091         return sdb;
5092 }
5093
5094 /****************************************************************************
5095  Get a security desc for a printer.
5096 ****************************************************************************/
5097
5098 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5099 {
5100         prs_struct ps;
5101         char *key;
5102         char *temp;
5103
5104         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5105                 sharename = temp + 1;
5106         }
5107
5108         /* Fetch security descriptor from tdb */
5109
5110         key = make_printers_secdesc_tdbkey( sharename  );
5111
5112         if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
5113             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5114
5115                 DEBUG(4,("using default secdesc for %s\n", sharename));
5116
5117                 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5118                         return False;
5119                 }
5120
5121                 /* Save default security descriptor for later */
5122
5123                 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
5124                                 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5125
5126                 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
5127                         tdb_prs_store(tdb_printers, key, &ps);
5128
5129                 prs_mem_free(&ps);
5130
5131                 return True;
5132         }
5133
5134         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5135            this security descriptor has been created when winbindd was
5136            down.  Take ownership of security descriptor. */
5137
5138         if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
5139                 DOM_SID owner_sid;
5140
5141                 /* Change sd owner to workgroup administrator */
5142
5143                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5144                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5145                         SEC_DESC *psd = NULL;
5146                         size_t size;
5147
5148                         /* Create new sd */
5149
5150                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5151
5152                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
5153                                             &owner_sid,
5154                                             (*secdesc_ctr)->sec->grp_sid,
5155                                             (*secdesc_ctr)->sec->sacl,
5156                                             (*secdesc_ctr)->sec->dacl,
5157                                             &size);
5158
5159                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5160
5161                         /* Swap with other one */
5162
5163                         *secdesc_ctr = new_secdesc_ctr;
5164
5165                         /* Set it */
5166
5167                         nt_printing_setsec(sharename, *secdesc_ctr);
5168                 }
5169         }
5170
5171         if (DEBUGLEVEL >= 10) {
5172                 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
5173                 int i;
5174
5175                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
5176                            sharename, the_acl->num_aces));
5177
5178                 for (i = 0; i < the_acl->num_aces; i++) {
5179                         fstring sid_str;
5180
5181                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
5182
5183                         DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5184                                    the_acl->ace[i].type, the_acl->ace[i].flags, 
5185                                    the_acl->ace[i].info.mask)); 
5186                 }
5187         }
5188
5189         prs_mem_free(&ps);
5190         return True;
5191 }
5192
5193 /* error code:
5194         0: everything OK
5195         1: level not implemented
5196         2: file doesn't exist
5197         3: can't allocate memory
5198         4: can't free memory
5199         5: non existant struct
5200 */
5201
5202 /*
5203         A printer and a printer driver are 2 different things.
5204         NT manages them separatelly, Samba does the same.
5205         Why ? Simply because it's easier and it makes sense !
5206         
5207         Now explanation: You have 3 printers behind your samba server,
5208         2 of them are the same make and model (laser A and B). But laser B
5209         has an 3000 sheet feeder and laser A doesn't such an option.
5210         Your third printer is an old dot-matrix model for the accounting :-).
5211         
5212         If the /usr/local/samba/lib directory (default dir), you will have
5213         5 files to describe all of this.
5214         
5215         3 files for the printers (1 by printer):
5216                 NTprinter_laser A
5217                 NTprinter_laser B
5218                 NTprinter_accounting
5219         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5220                 NTdriver_printer model X
5221                 NTdriver_printer model Y
5222
5223 jfm: I should use this comment for the text file to explain
5224         same thing for the forms BTW.
5225         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5226
5227 */
5228
5229 /* Convert generic access rights to printer object specific access rights.
5230    It turns out that NT4 security descriptors use generic access rights and
5231    NT5 the object specific ones. */
5232
5233 void map_printer_permissions(SEC_DESC *sd)
5234 {
5235         int i;
5236
5237         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5238                 se_map_generic(&sd->dacl->ace[i].info.mask,
5239                                &printer_generic_mapping);
5240         }
5241 }
5242
5243 /****************************************************************************
5244  Check a user has permissions to perform the given operation.  We use the
5245  permission constants defined in include/rpc_spoolss.h to check the various
5246  actions we perform when checking printer access.
5247
5248    PRINTER_ACCESS_ADMINISTER:
5249        print_queue_pause, print_queue_resume, update_printer_sec,
5250        update_printer, spoolss_addprinterex_level_2,
5251        _spoolss_setprinterdata
5252
5253    PRINTER_ACCESS_USE:
5254        print_job_start
5255
5256    JOB_ACCESS_ADMINISTER:
5257        print_job_delete, print_job_pause, print_job_resume,
5258        print_queue_purge
5259
5260   Try access control in the following order (for performance reasons):
5261     1)  root ans SE_PRINT_OPERATOR can do anything (easy check) 
5262     2)  check security descriptor (bit comparisons in memory)
5263     3)  "printer admins" (may result in numerous calls to winbind)
5264
5265  ****************************************************************************/
5266 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5267 {
5268         SEC_DESC_BUF *secdesc = NULL;
5269         uint32 access_granted;
5270         NTSTATUS status;
5271         BOOL result;
5272         const char *pname;
5273         TALLOC_CTX *mem_ctx = NULL;
5274         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5275         
5276         /* If user is NULL then use the current_user structure */
5277
5278         if (!user)
5279                 user = &current_user;
5280
5281         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5282
5283         if ( user->uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5284                 return True;
5285         }
5286
5287         /* Get printer name */
5288
5289         pname = PRINTERNAME(snum);
5290
5291         if (!pname || !*pname) {
5292                 errno = EACCES;
5293                 return False;
5294         }
5295
5296         /* Get printer security descriptor */
5297
5298         if(!(mem_ctx = talloc_init("print_access_check"))) {
5299                 errno = ENOMEM;
5300                 return False;
5301         }
5302
5303         nt_printing_getsec(mem_ctx, pname, &secdesc);
5304
5305         if (access_type == JOB_ACCESS_ADMINISTER) {
5306                 SEC_DESC_BUF *parent_secdesc = secdesc;
5307
5308                 /* Create a child security descriptor to check permissions
5309                    against.  This is because print jobs are child objects
5310                    objects of a printer. */
5311
5312                 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5313
5314                 /* Now this is the bit that really confuses me.  The access
5315                    type needs to be changed from JOB_ACCESS_ADMINISTER to
5316                    PRINTER_ACCESS_ADMINISTER for this to work.  Something
5317                    to do with the child (job) object becoming like a
5318                    printer??  -tpot */
5319
5320                 access_type = PRINTER_ACCESS_ADMINISTER;
5321         }
5322         
5323         /* Check access */
5324         
5325         map_printer_permissions(secdesc->sec);
5326
5327         result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5328                                  &access_granted, &status);
5329
5330         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5331
5332         /* see if we need to try the printer admin list */
5333
5334         if ( access_granted == 0 ) {
5335                 if ( user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups) )
5336                         return True;
5337         }
5338
5339         talloc_destroy(mem_ctx);
5340         
5341         if (!result)
5342                 errno = EACCES;
5343
5344         return result;
5345 }
5346
5347 /****************************************************************************
5348  Check the time parameters allow a print operation.
5349 *****************************************************************************/
5350
5351 BOOL print_time_access_check(int snum)
5352 {
5353         NT_PRINTER_INFO_LEVEL *printer = NULL;
5354         BOOL ok = False;
5355         time_t now = time(NULL);
5356         struct tm *t;
5357         uint32 mins;
5358
5359         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5360                 return False;
5361
5362         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5363                 ok = True;
5364
5365         t = gmtime(&now);
5366         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5367
5368         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5369                 ok = True;
5370
5371         free_a_printer(&printer, 2);
5372
5373         if (!ok)
5374                 errno = EACCES;
5375
5376         return ok;
5377 }
5378
5379 /****************************************************************************
5380  Fill in the servername sent in the _spoolss_open_printer_ex() call
5381 ****************************************************************************/
5382
5383 char* get_server_name( Printer_entry *printer )
5384 {
5385         return printer->servername;
5386 }
5387
5388