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