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