r13316: Let the carnage begin....
[ira/wip.git] / source / printing / nt_printing.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2000.
6  *  Copyright (C) Gerald Carter                2002-2005.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 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, NORMAL_CLOSE);
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, NORMAL_CLOSE);
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, NORMAL_CLOSE);
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, NORMAL_CLOSE);
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, NORMAL_CLOSE);
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 #ifdef HAVE_KCM
3144         setenv(KRB5_ENV_CCNAME, "KCM:SYSTEM", 1);
3145 #else
3146         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3147 #endif
3148         SAFE_FREE(ads->auth.password);
3149         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3150                 NULL, NULL);
3151
3152         /* ads_connect() will find the DC for us */                                         
3153         ads_rc = ads_connect(ads);
3154         if (!ADS_ERR_OK(ads_rc)) {
3155                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3156                 win_rc = WERR_ACCESS_DENIED;
3157                 goto done;
3158         }
3159
3160         switch (action) {
3161         case SPOOL_DS_PUBLISH:
3162         case SPOOL_DS_UPDATE:
3163                 win_rc = nt_printer_publish_ads(ads, printer);
3164                 break;
3165         case SPOOL_DS_UNPUBLISH:
3166                 win_rc = nt_printer_unpublish_ads(ads, printer);
3167                 break;
3168         }
3169
3170 done:
3171         free_a_printer(&printer, 2);
3172         ads_destroy(&ads);
3173         return win_rc;
3174 }
3175
3176 WERROR check_published_printers(void)
3177 {
3178         ADS_STATUS ads_rc;
3179         ADS_STRUCT *ads = NULL;
3180         int snum;
3181         int n_services = lp_numservices();
3182         NT_PRINTER_INFO_LEVEL *printer = NULL;
3183
3184         ads = ads_init(NULL, NULL, NULL);
3185         if (!ads) {
3186                 DEBUG(3, ("ads_init() failed\n"));
3187                 return WERR_SERVER_UNAVAILABLE;
3188         }
3189         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3190         SAFE_FREE(ads->auth.password);
3191         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3192                 NULL, NULL);
3193
3194         /* ads_connect() will find the DC for us */                                         
3195         ads_rc = ads_connect(ads);
3196         if (!ADS_ERR_OK(ads_rc)) {
3197                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3198                 ads_destroy(&ads);
3199                 return WERR_ACCESS_DENIED;
3200         }
3201
3202         for (snum = 0; snum < n_services; snum++) {
3203                 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3204                         continue;
3205
3206                 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3207                                                 lp_servicename(snum))) &&
3208                     (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3209                         nt_printer_publish_ads(ads, printer);
3210
3211                 free_a_printer(&printer, 2);
3212         }
3213
3214         ads_destroy(&ads);
3215         return WERR_OK;
3216 }
3217
3218 BOOL is_printer_published(Printer_entry *print_hnd, int snum, 
3219                           struct uuid *guid)
3220 {
3221         NT_PRINTER_INFO_LEVEL *printer = NULL;
3222         REGVAL_CTR *ctr;
3223         REGISTRY_VALUE *guid_val;
3224         WERROR win_rc;
3225         int i;
3226
3227         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3228
3229         if (!W_ERROR_IS_OK(win_rc) ||
3230             !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3231             ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3232             !(ctr = printer->info_2->data->keys[i].values) ||
3233             !(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) 
3234         {
3235                 free_a_printer(&printer, 2);
3236                 return False;
3237         }
3238
3239         /* fetching printer guids really ought to be a separate function.. */
3240         if (guid && regval_size(guid_val) == sizeof(struct uuid))
3241                 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
3242
3243         free_a_printer(&printer, 2);
3244         return True;
3245 }
3246 #else
3247 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3248 {
3249         return WERR_OK;
3250 }
3251
3252 WERROR check_published_printers(void)
3253 {
3254         return WERR_OK;
3255 }
3256
3257 BOOL is_printer_published(Printer_entry *print_hnd, int snum, 
3258                           struct uuid *guid)
3259 {
3260         return False;
3261 }
3262 #endif /* HAVE_ADS */
3263
3264 /****************************************************************************
3265  ***************************************************************************/
3266  
3267 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3268 {
3269         NT_PRINTER_DATA *data;
3270         int             i;
3271         int             removed_keys = 0;
3272         int             empty_slot;
3273         
3274         data = p2->data;
3275         empty_slot = data->num_keys;
3276
3277         if ( !key )
3278                 return WERR_INVALID_PARAM;
3279         
3280         /* remove all keys */
3281
3282         if ( !strlen(key) ) {
3283         
3284                 TALLOC_FREE( data );
3285
3286                 p2->data = NULL;
3287
3288                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3289                         p2->printername ));
3290         
3291                 return WERR_OK;
3292         }
3293
3294         /* remove a specific key (and all subkeys) */
3295         
3296         for ( i=0; i<data->num_keys; i++ ) {
3297                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3298                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3299                                 data->keys[i].name));
3300                 
3301                         TALLOC_FREE( data->keys[i].name );
3302                         TALLOC_FREE( data->keys[i].values );
3303
3304                         /* mark the slot as empty */
3305
3306                         ZERO_STRUCTP( &data->keys[i] );
3307                 }
3308         }
3309
3310         /* find the first empty slot */
3311
3312         for ( i=0; i<data->num_keys; i++ ) {
3313                 if ( !data->keys[i].name ) {
3314                         empty_slot = i;
3315                         removed_keys++;
3316                         break;
3317                 }
3318         }
3319
3320         if ( i == data->num_keys )
3321                 /* nothing was removed */
3322                 return WERR_INVALID_PARAM;
3323
3324         /* move everything down */
3325         
3326         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3327                 if ( data->keys[i].name ) {
3328                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) ); 
3329                         ZERO_STRUCTP( &data->keys[i] );
3330                         empty_slot++;
3331                         removed_keys++;
3332                 }
3333         }
3334
3335         /* update count */
3336                 
3337         data->num_keys -= removed_keys;
3338
3339         /* sanity check to see if anything is left */
3340
3341         if ( !data->num_keys ) {
3342                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3343
3344                 SAFE_FREE( data->keys );
3345                 ZERO_STRUCTP( data );
3346         }
3347
3348         return WERR_OK;
3349 }
3350
3351 /****************************************************************************
3352  ***************************************************************************/
3353  
3354 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3355 {
3356         WERROR          result = WERR_OK;
3357         int             key_index;
3358         
3359         /* we must have names on non-zero length */
3360         
3361         if ( !key || !*key|| !value || !*value )
3362                 return WERR_INVALID_NAME;
3363                 
3364         /* find the printer key first */
3365
3366         key_index = lookup_printerkey( p2->data, key );
3367         if ( key_index == -1 )
3368                 return WERR_OK;
3369         
3370         /* make sure the value exists so we can return the correct error code */
3371         
3372         if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3373                 return WERR_BADFILE;
3374                 
3375         regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3376         
3377         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3378                 key, value ));
3379         
3380         return result;
3381 }
3382
3383 /****************************************************************************
3384  ***************************************************************************/
3385  
3386 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value, 
3387                            uint32 type, uint8 *data, int real_len )
3388 {
3389         WERROR          result = WERR_OK;
3390         int             key_index;
3391
3392         /* we must have names on non-zero length */
3393         
3394         if ( !key || !*key|| !value || !*value )
3395                 return WERR_INVALID_NAME;
3396                 
3397         /* find the printer key first */
3398         
3399         key_index = lookup_printerkey( p2->data, key );
3400         if ( key_index == -1 )
3401                 key_index = add_new_printer_key( p2->data, key );
3402                 
3403         if ( key_index == -1 )
3404                 return WERR_NOMEM;
3405         
3406         regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3407                 type, (const char *)data, real_len );
3408         
3409         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3410                 key, value, type, real_len  ));
3411         
3412         return result;
3413 }
3414
3415 /****************************************************************************
3416  ***************************************************************************/
3417  
3418 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3419 {
3420         int             key_index;
3421
3422         if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3423                 return NULL;
3424
3425         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3426                 key, value ));
3427
3428         return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3429 }
3430
3431 /****************************************************************************
3432  Unpack a list of registry values frem the TDB
3433  ***************************************************************************/
3434  
3435 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3436 {
3437         int             len = 0;
3438         uint32          type;
3439         pstring         string, valuename, keyname;
3440         char            *str;
3441         int             size;
3442         uint8           *data_p;
3443         REGISTRY_VALUE  *regval_p;
3444         int             key_index;
3445
3446         /* add the "PrinterDriverData" key first for performance reasons */
3447         
3448         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3449
3450         /* loop and unpack the rest of the registry values */
3451         
3452         while ( True ) {
3453         
3454                 /* check to see if there are any more registry values */
3455                 
3456                 regval_p = NULL;
3457                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);         
3458                 if ( !regval_p ) 
3459                         break;
3460
3461                 /* unpack the next regval */
3462                 
3463                 len += tdb_unpack(buf+len, buflen-len, "fdB",
3464                                   string,
3465                                   &type,
3466                                   &size,
3467                                   &data_p);
3468
3469                 /* lookup for subkey names which have a type of REG_NONE */
3470                 /* there's no data with this entry */
3471
3472                 if ( type == REG_NONE ) {
3473                         if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3474                                 add_new_printer_key( printer_data, string );
3475                         continue;
3476                 }
3477         
3478                 /*
3479                  * break of the keyname from the value name.  
3480                  * Valuenames can have embedded '\'s so be careful.
3481                  * only support one level of keys.  See the 
3482                  * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3483                  * -- jerry
3484                  */     
3485                  
3486                 str = strchr_m( string, '\\');
3487                 
3488                 /* Put in "PrinterDriverData" is no key specified */
3489                 
3490                 if ( !str ) {
3491                         pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3492                         pstrcpy( valuename, string );
3493                 }
3494                 else {
3495                         *str = '\0';
3496                         pstrcpy( keyname, string );
3497                         pstrcpy( valuename, str+1 );
3498                 }
3499                         
3500                 /* see if we need a new key */
3501                 
3502                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3503                         key_index = add_new_printer_key( printer_data, keyname );
3504                         
3505                 if ( key_index == -1 ) {
3506                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3507                                 keyname));
3508                         break;
3509                 }
3510                 
3511                 /* add the new value */
3512                 
3513                 regval_ctr_addvalue( printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3514
3515                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3516
3517                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3518         }
3519
3520         return len;
3521 }
3522
3523 /****************************************************************************
3524  ***************************************************************************/
3525
3526 static void map_to_os2_driver(fstring drivername)
3527 {
3528         static BOOL initialised=False;
3529         static fstring last_from,last_to;
3530         char *mapfile = lp_os2_driver_map();
3531         char **lines = NULL;
3532         int numlines = 0;
3533         int i;
3534
3535         if (!strlen(drivername))
3536                 return;
3537
3538         if (!*mapfile)
3539                 return;
3540
3541         if (!initialised) {
3542                 *last_from = *last_to = 0;
3543                 initialised = True;
3544         }
3545
3546         if (strequal(drivername,last_from)) {
3547                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3548                 fstrcpy(drivername,last_to);
3549                 return;
3550         }
3551
3552         lines = file_lines_load(mapfile, &numlines,0);
3553         if (numlines == 0) {
3554                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3555                 return;
3556         }
3557
3558         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3559
3560         for( i = 0; i < numlines; i++) {
3561                 char *nt_name = lines[i];
3562                 char *os2_name = strchr(nt_name,'=');
3563
3564                 if (!os2_name)
3565                         continue;
3566
3567                 *os2_name++ = 0;
3568
3569                 while (isspace(*nt_name))
3570                         nt_name++;
3571
3572                 if (!*nt_name || strchr("#;",*nt_name))
3573                         continue;
3574
3575                 {
3576                         int l = strlen(nt_name);
3577                         while (l && isspace(nt_name[l-1])) {
3578                                 nt_name[l-1] = 0;
3579                                 l--;
3580                         }
3581                 }
3582
3583                 while (isspace(*os2_name))
3584                         os2_name++;
3585
3586                 {
3587                         int l = strlen(os2_name);
3588                         while (l && isspace(os2_name[l-1])) {
3589                                 os2_name[l-1] = 0;
3590                                 l--;
3591                         }
3592                 }
3593
3594                 if (strequal(nt_name,drivername)) {
3595                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3596                         fstrcpy(last_from,drivername);
3597                         fstrcpy(last_to,os2_name);
3598                         fstrcpy(drivername,os2_name);
3599                         file_lines_free(lines);
3600                         return;
3601                 }
3602         }
3603
3604         file_lines_free(lines);
3605 }
3606
3607 /****************************************************************************
3608  Get a default printer info 2 struct.
3609 ****************************************************************************/
3610 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
3611 {
3612         int snum;
3613
3614         snum = lp_servicenumber(sharename);
3615
3616         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3617         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s", 
3618                 servername, sharename);
3619         fstrcpy(info->sharename, sharename);
3620         fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3621
3622         /* by setting the driver name to an empty string, a local NT admin
3623            can now run the **local** APW to install a local printer driver
3624            for a Samba shared printer in 2.2.  Without this, drivers **must** be 
3625            installed on the Samba server for NT clients --jerry */
3626 #if 0   /* JERRY --do not uncomment-- */
3627         if (!*info->drivername)
3628                 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3629 #endif
3630
3631
3632         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3633
3634         pstrcpy(info->comment, "");
3635         fstrcpy(info->printprocessor, "winprint");
3636         fstrcpy(info->datatype, "RAW");
3637
3638         info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3639
3640         info->starttime = 0; /* Minutes since 12:00am GMT */
3641         info->untiltime = 0; /* Minutes since 12:00am GMT */
3642         info->priority = 1;
3643         info->default_priority = 1;
3644         info->setuptime = (uint32)time(NULL);
3645
3646         /*
3647          * I changed this as I think it is better to have a generic
3648          * DEVMODE than to crash Win2k explorer.exe   --jerry
3649          * See the HP Deskjet 990c Win2k drivers for an example.
3650          *
3651          * However the default devmode appears to cause problems
3652          * with the HP CLJ 8500 PCL driver.  Hence the addition of
3653          * the "default devmode" parameter   --jerry 22/01/2002
3654          */
3655
3656         if (lp_default_devmode(snum)) {
3657                 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL)
3658                         goto fail;
3659         }
3660         else {
3661                 info->devmode = NULL;
3662         }
3663
3664         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf))
3665                 goto fail;
3666
3667         return WERR_OK;
3668
3669 fail:
3670         if (info->devmode)
3671                 free_nt_devicemode(&info->devmode);
3672
3673         return WERR_ACCESS_DENIED;
3674 }
3675
3676 /****************************************************************************
3677 ****************************************************************************/
3678 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
3679 {
3680         int len = 0;
3681         int snum = lp_servicenumber(sharename);
3682         TDB_DATA kbuf, dbuf;
3683         fstring printername;
3684         char adevice[MAXDEVICENAME];
3685                 
3686         kbuf = make_printer_tdbkey( sharename );
3687
3688         dbuf = tdb_fetch(tdb_printers, kbuf);
3689         if (!dbuf.dptr)
3690                 return get_a_printer_2_default(info, servername, sharename);
3691
3692         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3693                         &info->attributes,
3694                         &info->priority,
3695                         &info->default_priority,
3696                         &info->starttime,
3697                         &info->untiltime,
3698                         &info->status,
3699                         &info->cjobs,
3700                         &info->averageppm,
3701                         &info->changeid,
3702                         &info->c_setprinter,
3703                         &info->setuptime,
3704                         info->servername,
3705                         info->printername,
3706                         info->sharename,
3707                         info->portname,
3708                         info->drivername,
3709                         info->comment,
3710                         info->location,
3711                         info->sepfile,
3712                         info->printprocessor,
3713                         info->datatype,
3714                         info->parameters);
3715
3716         /* Samba has to have shared raw drivers. */
3717         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3718         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3719
3720         /* Restore the stripped strings. */
3721         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3722
3723         if ( lp_force_printername(snum) )
3724                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3725         else 
3726                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3727
3728         fstrcpy(info->printername, printername);
3729
3730         len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
3731
3732         /*
3733          * Some client drivers freak out if there is a NULL devmode
3734          * (probably the driver is not checking before accessing 
3735          * the devmode pointer)   --jerry
3736          *
3737          * See comments in get_a_printer_2_default()
3738          */
3739
3740         if (lp_default_devmode(snum) && !info->devmode) {
3741                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3742                         printername));
3743                 info->devmode = construct_nt_devicemode(printername);
3744         }
3745
3746         slprintf( adevice, sizeof(adevice), "%s", info->printername );
3747         if (info->devmode) {
3748                 fstrcpy(info->devmode->devicename, adevice);    
3749         }
3750
3751         if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
3752                 DEBUG(0,("unpack_values: talloc() failed!\n"));
3753                 return WERR_NOMEM;
3754         }
3755         len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
3756
3757         /* This will get the current RPC talloc context, but we should be
3758            passing this as a parameter... fixme... JRA ! */
3759
3760         nt_printing_getsec(info, sharename, &info->secdesc_buf);
3761
3762         /* Fix for OS/2 drivers. */
3763
3764         if (get_remote_arch() == RA_OS2)
3765                 map_to_os2_driver(info->drivername);
3766
3767         SAFE_FREE(dbuf.dptr);
3768
3769         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3770                  sharename, info->printername, info->drivername));
3771
3772         return WERR_OK; 
3773 }
3774
3775 /****************************************************************************
3776  Debugging function, dump at level 6 the struct in the logs.
3777 ****************************************************************************/
3778 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3779 {
3780         uint32 result;
3781         NT_PRINTER_INFO_LEVEL_2 *info2;
3782         
3783         DEBUG(106,("Dumping printer at level [%d]\n", level));
3784         
3785         switch (level) {
3786                 case 2:
3787                 {
3788                         if (printer->info_2 == NULL)
3789                                 result=5;
3790                         else
3791                         {
3792                                 info2=printer->info_2;
3793                         
3794                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3795                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3796                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3797                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3798                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3799                                 DEBUGADD(106,("status:[%d]\n", info2->status));
3800                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3801                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3802                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3803                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3804                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3805
3806                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3807                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3808                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3809                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3810                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3811                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3812                                 DEBUGADD(106,("location:[%s]\n", info2->location));
3813                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3814                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3815                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3816                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3817                                 result=0;
3818                         }
3819                         break;
3820                 }
3821                 default:
3822                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3823                         result=1;
3824                         break;
3825         }
3826         
3827         return result;
3828 }
3829
3830 /****************************************************************************
3831  Update the changeid time.
3832  This is SO NASTY as some drivers need this to change, others need it
3833  static. This value will change every second, and I must hope that this
3834  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3835  UTAH ! JRA.
3836 ****************************************************************************/
3837
3838 static uint32 rev_changeid(void)
3839 {
3840         struct timeval tv;
3841
3842         get_process_uptime(&tv);
3843
3844 #if 1   /* JERRY */
3845         /* Return changeid as msec since spooler restart */
3846         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3847 #else
3848         /*
3849          * This setting seems to work well but is too untested
3850          * to replace the above calculation.  Left in for experiementation
3851          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
3852          */
3853         return tv.tv_sec * 10 + tv.tv_usec / 100000;
3854 #endif
3855 }
3856
3857
3858 /*
3859  * The function below are the high level ones.
3860  * only those ones must be called from the spoolss code.
3861  * JFM.
3862  */
3863
3864 /****************************************************************************
3865  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3866 ****************************************************************************/
3867
3868 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3869 {
3870         WERROR result;
3871         
3872         dump_a_printer(printer, level); 
3873         
3874         switch (level) {
3875                 case 2:
3876                 {
3877                         /*
3878                          * Update the changestamp.  Emperical tests show that the
3879                          * ChangeID is always updated,but c_setprinter is  
3880                          *  global spooler variable (not per printer).
3881                          */
3882
3883                         /* ChangeID **must** be increasing over the lifetime
3884                            of client's spoolss service in order for the
3885                            client's cache to show updates */
3886
3887                         printer->info_2->changeid = rev_changeid();
3888
3889                         /*
3890                          * Because one day someone will ask:
3891                          * NT->NT       An admin connection to a remote
3892                          *              printer show changes imeediately in
3893                          *              the properities dialog
3894                          *      
3895                          *              A non-admin connection will only show the
3896                          *              changes after viewing the properites page
3897                          *              2 times.  Seems to be related to a
3898                          *              race condition in the client between the spooler
3899                          *              updating the local cache and the Explorer.exe GUI
3900                          *              actually displaying the properties.
3901                          *
3902                          *              This is fixed in Win2k.  admin/non-admin
3903                          *              connections both display changes immediately.
3904                          *
3905                          * 14/12/01     --jerry
3906                          */
3907
3908                         result=update_a_printer_2(printer->info_2);
3909                         
3910                         break;
3911                 }
3912                 default:
3913                         result=WERR_UNKNOWN_LEVEL;
3914                         break;
3915         }
3916         
3917         return result;
3918 }
3919
3920 /****************************************************************************
3921  Initialize printer devmode & data with previously saved driver init values.
3922 ****************************************************************************/
3923
3924 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3925 {
3926         int                     len = 0;
3927         pstring                 key;
3928         TDB_DATA                kbuf, dbuf;
3929         NT_PRINTER_INFO_LEVEL_2 info;
3930
3931
3932         ZERO_STRUCT(info);
3933
3934         /*
3935          * Delete any printer data 'values' already set. When called for driver
3936          * replace, there will generally be some, but during an add printer, there
3937          * should not be any (if there are delete them).
3938          */
3939          
3940         if ( info_ptr->data )
3941                 delete_all_printer_data( info_ptr, "" );
3942         
3943         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3944
3945         kbuf.dptr = key;
3946         kbuf.dsize = strlen(key)+1;
3947
3948         dbuf = tdb_fetch(tdb_drivers, kbuf);
3949         if (!dbuf.dptr) {
3950                 /*
3951                  * When changing to a driver that has no init info in the tdb, remove
3952                  * the previous drivers init info and leave the new on blank.
3953                  */
3954                 free_nt_devicemode(&info_ptr->devmode);
3955                 return False;
3956         }
3957         
3958         /*
3959          * Get the saved DEVMODE..
3960          */
3961          
3962         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3963
3964         /*
3965          * The saved DEVMODE contains the devicename from the printer used during
3966          * the initialization save. Change it to reflect the new printer.
3967          */
3968          
3969         if ( info.devmode ) {
3970                 ZERO_STRUCT(info.devmode->devicename);
3971                 fstrcpy(info.devmode->devicename, info_ptr->printername);
3972         }
3973
3974         /*
3975          * NT/2k does not change out the entire DeviceMode of a printer
3976          * when changing the driver.  Only the driverextra, private, & 
3977          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
3978          *
3979          * Later examination revealed that Windows NT/2k does reset the
3980          * the printer's device mode, bit **only** when you change a 
3981          * property of the device mode such as the page orientation.
3982          * --jerry
3983          */
3984
3985
3986         /* Bind the saved DEVMODE to the new the printer */
3987          
3988         free_nt_devicemode(&info_ptr->devmode);
3989         info_ptr->devmode = info.devmode;
3990
3991         DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3992                 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3993
3994         /* Add the printer data 'values' to the new printer */
3995
3996         if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
3997                 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
3998                 return False;
3999         }
4000          
4001         len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4002         
4003
4004         SAFE_FREE(dbuf.dptr);
4005
4006         return True;    
4007 }
4008
4009 /****************************************************************************
4010  Initialize printer devmode & data with previously saved driver init values.
4011  When a printer is created using AddPrinter, the drivername bound to the
4012  printer is used to lookup previously saved driver initialization info, which
4013  is bound to the new printer.
4014 ****************************************************************************/
4015
4016 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4017 {
4018         BOOL result = False;
4019         
4020         switch (level) {
4021                 case 2:
4022                         result = set_driver_init_2(printer->info_2);
4023                         break;
4024                         
4025                 default:
4026                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
4027                                 level));
4028                         break;
4029         }
4030         
4031         return result;
4032 }
4033
4034 /****************************************************************************
4035  Delete driver init data stored for a specified driver
4036 ****************************************************************************/
4037
4038 BOOL del_driver_init(char *drivername)
4039 {
4040         pstring key;
4041         TDB_DATA kbuf;
4042
4043         if (!drivername || !*drivername) {
4044                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4045                 return False;
4046         }
4047
4048         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
4049
4050         kbuf.dptr = key;
4051         kbuf.dsize = strlen(key)+1;
4052
4053         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
4054
4055         return (tdb_delete(tdb_drivers, kbuf) == 0);
4056 }
4057
4058 /****************************************************************************
4059  Pack up the DEVMODE and values for a printer into a 'driver init' entry 
4060  in the tdb. Note: this is different from the driver entry and the printer
4061  entry. There should be a single driver init entry for each driver regardless
4062  of whether it was installed from NT or 2K. Technically, they should be
4063  different, but they work out to the same struct.
4064 ****************************************************************************/
4065
4066 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4067 {
4068         pstring key;
4069         char *buf;
4070         int buflen, len, ret;
4071         TDB_DATA kbuf, dbuf;
4072
4073         buf = NULL;
4074         buflen = 0;
4075
4076  again: 
4077         len = 0;
4078         len += pack_devicemode(info->devmode, buf+len, buflen-len);
4079
4080         len += pack_values( info->data, buf+len, buflen-len );
4081
4082         if (buflen < len) {
4083                 char *tb;
4084
4085                 tb = (char *)SMB_REALLOC(buf, len);
4086                 if (!tb) {
4087                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4088                         ret = -1;
4089                         goto done;
4090                 }
4091                 else
4092                         buf = tb;
4093                 buflen = len;
4094                 goto again;
4095         }
4096
4097         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4098
4099         kbuf.dptr = key;
4100         kbuf.dsize = strlen(key)+1;
4101         dbuf.dptr = buf;
4102         dbuf.dsize = len;
4103
4104         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
4105
4106 done:
4107         if (ret == -1)
4108                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4109
4110         SAFE_FREE(buf);
4111
4112         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4113                  info->sharename, info->drivername));
4114
4115         return ret;
4116 }
4117
4118 /****************************************************************************
4119  Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4120 ****************************************************************************/
4121
4122 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4123 {
4124         uint32 result;
4125         
4126         dump_a_printer(printer, level); 
4127         
4128         switch (level) {
4129                 case 2:
4130                         result = update_driver_init_2(printer->info_2);
4131                         break;
4132                 default:
4133                         result = 1;
4134                         break;
4135         }
4136         
4137         return result;
4138 }
4139
4140 /****************************************************************************
4141  Convert the printer data value, a REG_BINARY array, into an initialization 
4142  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4143  got to keep the endians happy :).
4144 ****************************************************************************/
4145
4146 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4147 {
4148         BOOL       result = False;
4149         prs_struct ps;
4150         DEVICEMODE devmode;
4151
4152         ZERO_STRUCT(devmode);
4153
4154         prs_init(&ps, 0, ctx, UNMARSHALL);
4155         ps.data_p      = (char *)data;
4156         ps.buffer_size = data_len;
4157
4158         if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4159                 result = convert_devicemode("", &devmode, &nt_devmode);
4160         else
4161                 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4162
4163         return result;
4164 }
4165
4166 /****************************************************************************
4167  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4168
4169  1. Use the driver's config DLL to this UNC printername and:
4170     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4171     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4172  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4173
4174  The last step triggers saving the "driver initialization" information for
4175  this printer into the tdb. Later, new printers that use this driver will
4176  have this initialization information bound to them. This simulates the
4177  driver initialization, as if it had run on the Samba server (as it would
4178  have done on NT).
4179
4180  The Win32 client side code requirement sucks! But until we can run arbitrary
4181  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4182  
4183  It would have been easier to use SetPrinter because all the UNMARSHALLING of
4184  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4185  about it and you will realize why.  JRR 010720
4186 ****************************************************************************/
4187
4188 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4189 {
4190         WERROR        status       = WERR_OK;
4191         TALLOC_CTX    *ctx         = NULL;
4192         NT_DEVICEMODE *nt_devmode  = NULL;
4193         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4194         
4195         /*
4196          * When the DEVMODE is already set on the printer, don't try to unpack it.
4197          */
4198         DEBUG(8,("save_driver_init_2: Enter...\n"));
4199         
4200         if ( !printer->info_2->devmode && data_len ) {
4201                 /*
4202                  * Set devmode on printer info, so entire printer initialization can be
4203                  * saved to tdb.
4204                  */
4205
4206                 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4207                         return WERR_NOMEM;
4208
4209                 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4210                         status = WERR_NOMEM;
4211                         goto done;
4212                 }
4213         
4214                 ZERO_STRUCTP(nt_devmode);
4215
4216                 /*
4217                  * The DEVMODE is held in the 'data' component of the param in raw binary.
4218                  * Convert it to to a devmode structure
4219                  */
4220                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4221                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4222                         status = WERR_INVALID_PARAM;
4223                         goto done;
4224                 }
4225
4226                 printer->info_2->devmode = nt_devmode;
4227         }
4228
4229         /*
4230          * Pack up and add (or update) the DEVMODE and any current printer data to
4231          * a 'driver init' element in the tdb
4232          * 
4233          */
4234
4235         if ( update_driver_init(printer, 2) != 0 ) {
4236                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4237                 status = WERR_NOMEM;
4238                 goto done;
4239         }
4240         
4241         /*
4242          * If driver initialization info was successfully saved, set the current 
4243          * printer to match it. This allows initialization of the current printer 
4244          * as well as the driver.
4245          */
4246         status = mod_a_printer(printer, 2);
4247         if (!W_ERROR_IS_OK(status)) {
4248                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4249                                   printer->info_2->printername));
4250         }
4251         
4252   done:
4253         talloc_destroy(ctx);
4254         free_nt_devicemode( &nt_devmode );
4255         
4256         printer->info_2->devmode = tmp_devmode;
4257
4258         return status;
4259 }
4260
4261 /****************************************************************************
4262  Update the driver init info (DEVMODE and specifics) for a printer
4263 ****************************************************************************/
4264
4265 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4266 {
4267         WERROR status = WERR_OK;
4268         
4269         switch (level) {
4270                 case 2:
4271                         status = save_driver_init_2( printer, data, data_len );
4272                         break;
4273                 default:
4274                         status = WERR_UNKNOWN_LEVEL;
4275                         break;
4276         }
4277         
4278         return status;
4279 }
4280
4281 /****************************************************************************
4282  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4283
4284  Previously the code had a memory allocation problem because it always
4285  used the TALLOC_CTX from the Printer_entry*.   This context lasts 
4286  as a long as the original handle is open.  So if the client made a lot 
4287  of getprinter[data]() calls, the memory usage would climb.  Now we use
4288  a short lived TALLOC_CTX for printer_info_2 objects returned.  We 
4289  still use the Printer_entry->ctx for maintaining the cache copy though
4290  since that object must live as long as the handle by definition.  
4291                                                     --jerry
4292
4293 ****************************************************************************/
4294
4295 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, 
4296                         const char *sharename)
4297 {
4298         WERROR result;
4299         fstring servername;
4300         
4301         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4302
4303         if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4304                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4305                 return WERR_NOMEM;
4306         }
4307
4308         switch (level) {
4309                 case 2:
4310                         if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4311                                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4312                                 TALLOC_FREE( *pp_printer );
4313                                 return WERR_NOMEM;
4314                         }
4315
4316                         if ( print_hnd ) 
4317                                 fstrcpy( servername, print_hnd->servername );
4318                         else {
4319                                 fstrcpy( servername, "%L" );
4320                                 standard_sub_basic( "", servername, sizeof(servername)-1 );
4321                         }
4322
4323                         result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4324         
4325                         
4326                         /* we have a new printer now.  Save it with this handle */
4327                         
4328                         if ( !W_ERROR_IS_OK(result) ) {
4329                                 TALLOC_FREE( *pp_printer );
4330                                 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", 
4331                                         sharename, (unsigned int)level, dos_errstr(result)));
4332                                 return result;
4333                         }
4334
4335                         dump_a_printer( *pp_printer, level);
4336                         
4337                         break;
4338                         
4339                 default:
4340                         TALLOC_FREE( *pp_printer );
4341                         return WERR_UNKNOWN_LEVEL;
4342         }
4343         
4344         return WERR_OK;
4345 }
4346
4347 /****************************************************************************
4348  Deletes a NT_PRINTER_INFO_LEVEL struct.
4349 ****************************************************************************/
4350
4351 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4352 {
4353         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4354
4355         if ( !printer )
4356                 return 0;
4357         
4358         switch (level) {
4359                 case 2:
4360                         if ( printer->info_2 ) 
4361                                 free_nt_printer_info_level_2(&printer->info_2);
4362                         break;
4363
4364                 default:
4365                         DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4366                         return 1;
4367         }
4368
4369         TALLOC_FREE(*pp_printer);
4370
4371         return 0;
4372 }
4373
4374 /****************************************************************************
4375 ****************************************************************************/
4376 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4377 {
4378         uint32 result;
4379         DEBUG(104,("adding a printer at level [%d]\n", level));
4380         dump_a_printer_driver(driver, level);
4381         
4382         switch (level) {
4383                 case 3:
4384                         result=add_a_printer_driver_3(driver.info_3);
4385                         break;
4386
4387                 case 6:
4388                         result=add_a_printer_driver_6(driver.info_6);
4389                         break;
4390
4391                 default:
4392                         result=1;
4393                         break;
4394         }
4395         
4396         return result;
4397 }
4398 /****************************************************************************
4399 ****************************************************************************/
4400
4401 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4402                             fstring drivername, const char *architecture, uint32 version)
4403 {
4404         WERROR result;
4405         
4406         switch (level) {
4407                 case 3:
4408                         /* Sometime we just want any version of the driver */
4409                         
4410                         if ( version == DRIVER_ANY_VERSION ) {
4411                                 /* look for Win2k first and then for NT4 */
4412                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4413                                                 architecture, 3);
4414                                                 
4415                                 if ( !W_ERROR_IS_OK(result) ) {
4416                                         result = get_a_printer_driver_3( &driver->info_3, 
4417                                                         drivername, architecture, 2 );
4418                                 }
4419                         } else {
4420                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4421                                         architecture, version);                         
4422                         }
4423                         break;
4424                         
4425                 default:
4426                         result=W_ERROR(1);
4427                         break;
4428         }
4429         
4430         if (W_ERROR_IS_OK(result))
4431                 dump_a_printer_driver(*driver, level);
4432                 
4433         return result;
4434 }
4435
4436 /****************************************************************************
4437 ****************************************************************************/
4438 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4439 {
4440         uint32 result;
4441         
4442         switch (level) {
4443                 case 3:
4444                 {
4445                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4446                         if (driver.info_3 != NULL)
4447                         {
4448                                 info3=driver.info_3;
4449                                 SAFE_FREE(info3->dependentfiles);
4450                                 ZERO_STRUCTP(info3);
4451                                 SAFE_FREE(info3);
4452                                 result=0;
4453                         } else {
4454                                 result=4;
4455                         }
4456                         break;
4457                 }
4458                 case 6:
4459                 {
4460                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4461                         if (driver.info_6 != NULL) {
4462                                 info6=driver.info_6;
4463                                 SAFE_FREE(info6->dependentfiles);
4464                                 SAFE_FREE(info6->previousnames);
4465                                 ZERO_STRUCTP(info6);
4466                                 SAFE_FREE(info6);
4467                                 result=0;
4468                         } else {
4469                                 result=4;
4470                         }
4471                         break;
4472                 }
4473                 default:
4474                         result=1;
4475                         break;
4476         }
4477         return result;
4478 }
4479
4480
4481 /****************************************************************************
4482   Determine whether or not a particular driver is currently assigned
4483   to a printer
4484 ****************************************************************************/
4485
4486 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4487 {
4488         int snum;
4489         int n_services = lp_numservices();
4490         NT_PRINTER_INFO_LEVEL *printer = NULL;
4491         BOOL in_use = False;
4492
4493         if ( !info_3 ) 
4494                 return False;
4495
4496         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4497         
4498         /* loop through the printers.tdb and check for the drivername */
4499         
4500         for (snum=0; snum<n_services && !in_use; snum++) {
4501                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4502                         continue;
4503                 
4504                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4505                         continue;
4506                 
4507                 if ( strequal(info_3->name, printer->info_2->drivername) ) 
4508                         in_use = True;
4509                 
4510                 free_a_printer( &printer, 2 );
4511         }
4512         
4513         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4514         
4515         if ( in_use ) {
4516                 NT_PRINTER_DRIVER_INFO_LEVEL d;
4517                 WERROR werr;
4518                 
4519                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4520                 
4521                 /* we can still remove the driver if there is one of 
4522                    "Windows NT x86" version 2 or 3 left */
4523                    
4524                 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4525                         werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );                       
4526                 }
4527                 else {
4528                         switch ( info_3->cversion ) {
4529                         case 2:
4530                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4531                                 break;
4532                         case 3: 
4533                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4534                                 break;
4535                         default:
4536                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n", 
4537                                         info_3->cversion));
4538                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4539                                 break;
4540                         }
4541                 }
4542
4543                 /* now check the error code */
4544                                 
4545                 if ( W_ERROR_IS_OK(werr) ) {
4546                         /* it's ok to remove the driver, we have other architctures left */
4547                         in_use = False;
4548                         free_a_printer_driver( d, 3 );
4549                 }
4550         }
4551         
4552         /* report that the driver is not in use by default */
4553         
4554         return in_use;
4555 }
4556
4557
4558 /**********************************************************************
4559  Check to see if a ogiven file is in use by *info
4560  *********************************************************************/
4561  
4562 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4563 {
4564         int i = 0;
4565         
4566         if ( !info )
4567                 return False;
4568                 
4569         if ( strequal(file, info->driverpath) )
4570                 return True;
4571
4572         if ( strequal(file, info->datafile) )
4573                 return True;
4574
4575         if ( strequal(file, info->configfile) )
4576                 return True;
4577
4578         if ( strequal(file, info->helpfile) )
4579                 return True;
4580         
4581         /* see of there are any dependent files to examine */
4582         
4583         if ( !info->dependentfiles )
4584                 return False;
4585         
4586         while ( *info->dependentfiles[i] ) {
4587                 if ( strequal(file, info->dependentfiles[i]) )
4588                         return True;
4589                 i++;
4590         }
4591         
4592         return False;
4593
4594 }
4595
4596 /**********************************************************************
4597  Utility function to remove the dependent file pointed to by the 
4598  input parameter from the list 
4599  *********************************************************************/
4600
4601 static void trim_dependent_file( fstring files[], int idx )
4602 {
4603         
4604         /* bump everything down a slot */
4605
4606         while( *files[idx+1] ) {
4607                 fstrcpy( files[idx], files[idx+1] );
4608                 idx++;
4609         }
4610         
4611         *files[idx] = '\0';
4612
4613         return; 
4614 }
4615
4616 /**********************************************************************
4617  Check if any of the files used by src are also used by drv 
4618  *********************************************************************/
4619
4620 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, 
4621                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4622 {
4623         BOOL    in_use = False;
4624         int     i = 0;
4625         
4626         if ( !src || !drv )
4627                 return False;
4628                 
4629         /* check each file.  Remove it from the src structure if it overlaps */
4630         
4631         if ( drv_file_in_use(src->driverpath, drv) ) {
4632                 in_use = True;
4633                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4634                 fstrcpy( src->driverpath, "" );
4635         }
4636                 
4637         if ( drv_file_in_use(src->datafile, drv) ) {
4638                 in_use = True;
4639                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4640                 fstrcpy( src->datafile, "" );
4641         }
4642                 
4643         if ( drv_file_in_use(src->configfile, drv) ) {
4644                 in_use = True;
4645                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4646                 fstrcpy( src->configfile, "" );
4647         }
4648                 
4649         if ( drv_file_in_use(src->helpfile, drv) ) {
4650                 in_use = True;
4651                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4652                 fstrcpy( src->helpfile, "" );
4653         }
4654         
4655         /* are there any dependentfiles to examine? */
4656         
4657         if ( !src->dependentfiles )
4658                 return in_use;
4659                 
4660         while ( *src->dependentfiles[i] ) {
4661                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4662                         in_use = True;
4663                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4664                         trim_dependent_file( src->dependentfiles, i );
4665                 } else
4666                         i++;
4667         }               
4668                 
4669         return in_use;
4670 }
4671
4672 /****************************************************************************
4673   Determine whether or not a particular driver files are currently being 
4674   used by any other driver.  
4675   
4676   Return value is True if any files were in use by other drivers
4677   and False otherwise.
4678   
4679   Upon return, *info has been modified to only contain the driver files
4680   which are not in use
4681 ****************************************************************************/
4682
4683 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4684 {
4685         int                             i;
4686         int                             ndrivers;
4687         uint32                          version;
4688         fstring                         *list = NULL;
4689         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
4690         
4691         if ( !info )
4692                 return False;
4693         
4694         version = info->cversion;
4695         
4696         /* loop over all driver versions */
4697         
4698         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4699         
4700         /* get the list of drivers */
4701                 
4702         list = NULL;
4703         ndrivers = get_ntdrivers(&list, info->environment, version);
4704                 
4705         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
4706                 ndrivers, info->environment, version));
4707
4708         /* check each driver for overlap in files */
4709                 
4710         for (i=0; i<ndrivers; i++) {
4711                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4712                         
4713                 ZERO_STRUCT(driver);
4714                         
4715                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4716                         SAFE_FREE(list);
4717                         return True;
4718                 }
4719                         
4720                 /* check if d2 uses any files from d1 */
4721                 /* only if this is a different driver than the one being deleted */
4722                         
4723                 if ( !strequal(info->name, driver.info_3->name) ) {
4724                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
4725                                 free_a_printer_driver(driver, 3);
4726                                 SAFE_FREE( list );
4727                                 return True;
4728                         }
4729                 }
4730         
4731                 free_a_printer_driver(driver, 3);
4732         }       
4733         
4734         SAFE_FREE(list);
4735         
4736         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4737         
4738         driver.info_3 = info;
4739         
4740         if ( DEBUGLEVEL >= 20 )
4741                 dump_a_printer_driver( driver, 3 );
4742         
4743         return False;
4744 }
4745
4746 /****************************************************************************
4747   Actually delete the driver files.  Make sure that 
4748   printer_driver_files_in_use() return False before calling 
4749   this.
4750 ****************************************************************************/
4751
4752 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4753 {
4754         int i = 0;
4755         char *s;
4756         pstring file;
4757         connection_struct *conn;
4758         DATA_BLOB null_pw;
4759         NTSTATUS nt_status;
4760         fstring res_type;
4761         BOOL bad_path;
4762         SMB_STRUCT_STAT  st;
4763
4764         if ( !info_3 )
4765                 return False;
4766                 
4767         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4768         
4769         /*
4770          * Connect to the print$ share under the same account as the 
4771          * user connected to the rpc pipe. Note we must be root to 
4772          * do this.
4773          */
4774          
4775         null_pw = data_blob( NULL, 0 );
4776         fstrcpy(res_type, "A:");
4777         become_root();
4778         conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4779         unbecome_root();
4780         
4781         if ( !conn ) {
4782                 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4783                 return False;
4784         }
4785
4786         /* Save who we are - we are temporarily becoming the connection user. */
4787
4788         if ( !become_user(conn, conn->vuid) ) {
4789                 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4790                 return False;
4791         }
4792
4793         /* now delete the files; must strip the '\print$' string from 
4794            fron of path                                                */
4795         
4796         if ( *info_3->driverpath ) {
4797                 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4798                         pstrcpy( file, s );
4799                         driver_unix_convert(file, conn, NULL, &bad_path, &st);
4800                         DEBUG(10,("deleting driverfile [%s]\n", s));
4801                         unlink_internals(conn, 0, file, False);
4802                 }
4803         }
4804                 
4805         if ( *info_3->configfile ) {
4806                 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4807                         pstrcpy( file, s );
4808                         driver_unix_convert(file, conn, NULL, &bad_path, &st);
4809                         DEBUG(10,("deleting configfile [%s]\n", s));
4810                         unlink_internals(conn, 0, file, False);
4811                 }
4812         }
4813         
4814         if ( *info_3->datafile ) {
4815                 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4816                         pstrcpy( file, s );
4817                         driver_unix_convert(file, conn, NULL, &bad_path, &st);
4818                         DEBUG(10,("deleting datafile [%s]\n", s));
4819                         unlink_internals(conn, 0, file, False);
4820                 }
4821         }
4822         
4823         if ( *info_3->helpfile ) {
4824                 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4825                         pstrcpy( file, s );
4826                         driver_unix_convert(file, conn, NULL, &bad_path, &st);
4827                         DEBUG(10,("deleting helpfile [%s]\n", s));
4828                         unlink_internals(conn, 0, file, False);
4829                 }
4830         }
4831         
4832         /* check if we are done removing files */
4833         
4834         if ( info_3->dependentfiles ) {
4835                 while ( info_3->dependentfiles[i][0] ) {
4836                         char *p;
4837
4838                         /* bypass the "\print$" portion of the path */
4839                         
4840                         if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4841                                 pstrcpy( file, p );
4842                                 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4843                                 DEBUG(10,("deleting dependent file [%s]\n", file));
4844                                 unlink_internals(conn, 0, file, False);
4845                         }
4846                         
4847                         i++;
4848                 }
4849         }
4850
4851         unbecome_user();
4852         
4853         return True;
4854 }
4855
4856 /****************************************************************************
4857  Remove a printer driver from the TDB.  This assumes that the the driver was
4858  previously looked up.
4859  ***************************************************************************/
4860
4861 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4862                               uint32 version, BOOL delete_files )
4863 {
4864         pstring         key;
4865         const char     *arch;
4866         TDB_DATA        kbuf, dbuf;
4867         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
4868
4869         /* delete the tdb data first */
4870
4871         arch = get_short_archi(info_3->environment);
4872         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4873                 arch, version, info_3->name);
4874
4875         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4876                 key, delete_files ? "TRUE" : "FALSE" ));
4877
4878         ctr.info_3 = info_3;
4879         dump_a_printer_driver( ctr, 3 );
4880
4881         kbuf.dptr=key;
4882         kbuf.dsize=strlen(key)+1;
4883
4884         /* check if the driver actually exists for this environment */
4885         
4886         dbuf = tdb_fetch( tdb_drivers, kbuf );
4887         if ( !dbuf.dptr ) {
4888                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4889                 return WERR_UNKNOWN_PRINTER_DRIVER;
4890         }
4891                 
4892         SAFE_FREE( dbuf.dptr );
4893         
4894         /* ok... the driver exists so the delete should return success */
4895                 
4896         if (tdb_delete(tdb_drivers, kbuf) == -1) {
4897                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4898                 return WERR_ACCESS_DENIED;
4899         }
4900
4901         /*
4902          * now delete any associated files if delete_files == True
4903          * even if this part failes, we return succes because the
4904          * driver doesn not exist any more
4905          */
4906
4907         if ( delete_files )
4908                 delete_driver_files( info_3, user );
4909                         
4910                 
4911         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4912
4913         return WERR_OK;
4914         }
4915         
4916 /****************************************************************************
4917  Store a security desc for a printer.
4918 ****************************************************************************/
4919
4920 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
4921 {
4922         SEC_DESC_BUF *new_secdesc_ctr = NULL;
4923         SEC_DESC_BUF *old_secdesc_ctr = NULL;
4924         prs_struct ps;
4925         TALLOC_CTX *mem_ctx = NULL;
4926         char *key;
4927         WERROR status;
4928
4929         mem_ctx = talloc_init("nt_printing_setsec");
4930         if (mem_ctx == NULL)
4931                 return WERR_NOMEM;
4932
4933         /* The old owner and group sids of the security descriptor are not
4934            present when new ACEs are added or removed by changing printer
4935            permissions through NT.  If they are NULL in the new security
4936            descriptor then copy them over from the old one. */
4937
4938         if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4939                 DOM_SID *owner_sid, *group_sid;
4940                 SEC_ACL *dacl, *sacl;
4941                 SEC_DESC *psd = NULL;
4942                 size_t size;
4943
4944                 nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr);
4945
4946                 /* Pick out correct owner and group sids */
4947
4948                 owner_sid = secdesc_ctr->sec->owner_sid ?
4949                         secdesc_ctr->sec->owner_sid :
4950                         old_secdesc_ctr->sec->owner_sid;
4951
4952                 group_sid = secdesc_ctr->sec->grp_sid ?
4953                         secdesc_ctr->sec->grp_sid :
4954                         old_secdesc_ctr->sec->grp_sid;
4955
4956                 dacl = secdesc_ctr->sec->dacl ?
4957                         secdesc_ctr->sec->dacl :
4958                         old_secdesc_ctr->sec->dacl;
4959
4960                 sacl = secdesc_ctr->sec->sacl ?
4961                         secdesc_ctr->sec->sacl :
4962                         old_secdesc_ctr->sec->sacl;
4963
4964                 /* Make a deep copy of the security descriptor */
4965
4966                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4967                                     owner_sid, group_sid,
4968                                     sacl,
4969                                     dacl,
4970                                     &size);
4971
4972                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4973         }
4974
4975         if (!new_secdesc_ctr) {
4976                 new_secdesc_ctr = secdesc_ctr;
4977         }
4978
4979         /* Store the security descriptor in a tdb */
4980
4981         prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4982                  sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4983
4984         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4985                              &ps, 1)) {
4986                 status = WERR_BADFUNC;
4987                 goto out;
4988         }
4989
4990         key = make_printers_secdesc_tdbkey( sharename );
4991
4992         if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4993                 status = WERR_OK;
4994         } else {
4995                 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
4996                 status = WERR_BADFUNC;
4997         }
4998
4999         /* Free malloc'ed memory */
5000
5001  out:
5002
5003         prs_mem_free(&ps);
5004         if (mem_ctx)
5005                 talloc_destroy(mem_ctx);
5006         return status;
5007 }
5008
5009 /****************************************************************************
5010  Construct a default security descriptor buffer for a printer.
5011 ****************************************************************************/
5012
5013 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5014 {
5015         SEC_ACE ace[5]; /* max number of ace entries */
5016         int i = 0;
5017         SEC_ACCESS sa;
5018         SEC_ACL *psa = NULL;
5019         SEC_DESC_BUF *sdb = NULL;
5020         SEC_DESC *psd = NULL;
5021         DOM_SID adm_sid;
5022         size_t sd_size;
5023
5024         /* Create an ACE where Everyone is allowed to print */
5025
5026         init_sec_access(&sa, PRINTER_ACE_PRINT);
5027         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5028                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5029
5030         /* Add the domain admins group if we are a DC */
5031         
5032         if ( IS_DC ) {
5033                 DOM_SID domadmins_sid;
5034                 
5035                 sid_copy(&domadmins_sid, get_global_sam_sid());
5036                 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5037                 
5038                 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5039                 init_sec_ace(&ace[i++], &domadmins_sid, 
5040                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5041                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5042                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5043                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5044         }
5045         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5046                 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5047
5048                 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5049                 init_sec_ace(&ace[i++], &adm_sid, 
5050                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5051                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5052                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5053                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5054         }
5055
5056         /* add BUILTIN\Administrators as FULL CONTROL */
5057
5058         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5059         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 
5060                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5061                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5062         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 
5063                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5064                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5065
5066         /* Make the security descriptor owned by the BUILTIN\Administrators */
5067
5068         /* The ACL revision number in rpc_secdesc.h differs from the one
5069            created by NT when setting ACE entries in printer
5070            descriptors.  NT4 complains about the property being edited by a
5071            NT5 machine. */
5072
5073         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5074                 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5075                         &global_sid_Builtin_Administrators, 
5076                         &global_sid_Builtin_Administrators,
5077                         NULL, psa, &sd_size);
5078         }
5079
5080         if (!psd) {
5081                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5082                 return NULL;
5083         }
5084
5085         sdb = make_sec_desc_buf(ctx, sd_size, psd);
5086
5087         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5088                  (unsigned int)sd_size));
5089
5090         return sdb;
5091 }
5092
5093 /****************************************************************************
5094  Get a security desc for a printer.
5095 ****************************************************************************/
5096
5097 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5098 {
5099         prs_struct ps;
5100         char *key;
5101         char *temp;
5102
5103         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5104                 sharename = temp + 1;
5105         }
5106
5107         /* Fetch security descriptor from tdb */
5108
5109         key = make_printers_secdesc_tdbkey( sharename  );
5110
5111         if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
5112             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5113
5114                 DEBUG(4,("using default secdesc for %s\n", sharename));
5115
5116                 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5117                         return False;
5118                 }
5119
5120                 /* Save default security descriptor for later */
5121
5122                 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
5123                                 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5124
5125                 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
5126                         tdb_prs_store(tdb_printers, key, &ps);
5127
5128                 prs_mem_free(&ps);
5129
5130                 return True;
5131         }
5132
5133         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5134            this security descriptor has been created when winbindd was
5135            down.  Take ownership of security descriptor. */
5136
5137         if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
5138                 DOM_SID owner_sid;
5139
5140                 /* Change sd owner to workgroup administrator */
5141
5142                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5143                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5144                         SEC_DESC *psd = NULL;
5145                         size_t size;
5146
5147                         /* Create new sd */
5148
5149                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5150
5151                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
5152                                             &owner_sid,
5153                                             (*secdesc_ctr)->sec->grp_sid,
5154                                             (*secdesc_ctr)->sec->sacl,
5155                                             (*secdesc_ctr)->sec->dacl,
5156                                             &size);
5157
5158                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5159
5160                         /* Swap with other one */
5161
5162                         *secdesc_ctr = new_secdesc_ctr;
5163
5164                         /* Set it */
5165
5166                         nt_printing_setsec(sharename, *secdesc_ctr);
5167                 }
5168         }
5169
5170         if (DEBUGLEVEL >= 10) {
5171                 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
5172                 int i;
5173
5174                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
5175                            sharename, the_acl->num_aces));
5176
5177                 for (i = 0; i < the_acl->num_aces; i++) {
5178                         fstring sid_str;
5179
5180                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
5181
5182                         DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5183                                    the_acl->ace[i].type, the_acl->ace[i].flags, 
5184                                    the_acl->ace[i].info.mask)); 
5185                 }
5186         }
5187
5188         prs_mem_free(&ps);
5189         return True;
5190 }
5191
5192 /* error code:
5193         0: everything OK
5194         1: level not implemented
5195         2: file doesn't exist
5196         3: can't allocate memory
5197         4: can't free memory
5198         5: non existant struct
5199 */
5200
5201 /*
5202         A printer and a printer driver are 2 different things.
5203         NT manages them separatelly, Samba does the same.
5204         Why ? Simply because it's easier and it makes sense !
5205         
5206         Now explanation: You have 3 printers behind your samba server,
5207         2 of them are the same make and model (laser A and B). But laser B
5208         has an 3000 sheet feeder and laser A doesn't such an option.
5209         Your third printer is an old dot-matrix model for the accounting :-).
5210         
5211         If the /usr/local/samba/lib directory (default dir), you will have
5212         5 files to describe all of this.
5213         
5214         3 files for the printers (1 by printer):
5215                 NTprinter_laser A
5216                 NTprinter_laser B
5217                 NTprinter_accounting
5218         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5219                 NTdriver_printer model X
5220                 NTdriver_printer model Y
5221
5222 jfm: I should use this comment for the text file to explain
5223         same thing for the forms BTW.
5224         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5225
5226 */
5227
5228 /* Convert generic access rights to printer object specific access rights.
5229    It turns out that NT4 security descriptors use generic access rights and
5230    NT5 the object specific ones. */
5231
5232 void map_printer_permissions(SEC_DESC *sd)
5233 {
5234         int i;
5235
5236         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5237                 se_map_generic(&sd->dacl->ace[i].info.mask,
5238                                &printer_generic_mapping);
5239         }
5240 }
5241
5242 /****************************************************************************
5243  Check a user has permissions to perform the given operation.  We use the
5244  permission constants defined in include/rpc_spoolss.h to check the various
5245  actions we perform when checking printer access.
5246
5247    PRINTER_ACCESS_ADMINISTER:
5248        print_queue_pause, print_queue_resume, update_printer_sec,
5249        update_printer, spoolss_addprinterex_level_2,
5250        _spoolss_setprinterdata
5251
5252    PRINTER_ACCESS_USE:
5253        print_job_start
5254
5255    JOB_ACCESS_ADMINISTER:
5256        print_job_delete, print_job_pause, print_job_resume,
5257        print_queue_purge
5258
5259   Try access control in the following order (for performance reasons):
5260     1)  root ans SE_PRINT_OPERATOR can do anything (easy check) 
5261     2)  check security descriptor (bit comparisons in memory)
5262     3)  "printer admins" (may result in numerous calls to winbind)
5263
5264  ****************************************************************************/
5265 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5266 {
5267         SEC_DESC_BUF *secdesc = NULL;
5268         uint32 access_granted;
5269         NTSTATUS status;
5270         BOOL result;
5271         const char *pname;
5272         TALLOC_CTX *mem_ctx = NULL;
5273         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5274         
5275         /* If user is NULL then use the current_user structure */
5276
5277         if (!user)
5278                 user = &current_user;
5279
5280         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5281
5282         if ( user->ut.uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5283                 return True;
5284         }
5285
5286         /* Get printer name */
5287
5288         pname = PRINTERNAME(snum);
5289
5290         if (!pname || !*pname) {
5291                 errno = EACCES;
5292                 return False;
5293         }
5294
5295         /* Get printer security descriptor */
5296
5297         if(!(mem_ctx = talloc_init("print_access_check"))) {
5298                 errno = ENOMEM;
5299                 return False;
5300         }
5301
5302         nt_printing_getsec(mem_ctx, pname, &secdesc);
5303
5304         if (access_type == JOB_ACCESS_ADMINISTER) {
5305                 SEC_DESC_BUF *parent_secdesc = secdesc;
5306
5307                 /* Create a child security descriptor to check permissions
5308                    against.  This is because print jobs are child objects
5309                    objects of a printer. */
5310
5311                 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5312
5313                 /* Now this is the bit that really confuses me.  The access
5314                    type needs to be changed from JOB_ACCESS_ADMINISTER to
5315                    PRINTER_ACCESS_ADMINISTER for this to work.  Something
5316                    to do with the child (job) object becoming like a
5317                    printer??  -tpot */
5318
5319                 access_type = PRINTER_ACCESS_ADMINISTER;
5320         }
5321         
5322         /* Check access */
5323         
5324         map_printer_permissions(secdesc->sec);
5325
5326         result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5327                                  &access_granted, &status);
5328
5329         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5330
5331         /* see if we need to try the printer admin list */
5332
5333         if ((access_granted == 0) &&
5334             (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
5335                                          user->nt_user_token,
5336                                          lp_printer_admin(snum)))) {
5337                 return True;
5338         }
5339
5340         talloc_destroy(mem_ctx);
5341         
5342         if (!result)
5343                 errno = EACCES;
5344
5345         return result;
5346 }
5347
5348 /****************************************************************************
5349  Check the time parameters allow a print operation.
5350 *****************************************************************************/
5351
5352 BOOL print_time_access_check(int snum)
5353 {
5354         NT_PRINTER_INFO_LEVEL *printer = NULL;
5355         BOOL ok = False;
5356         time_t now = time(NULL);
5357         struct tm *t;
5358         uint32 mins;
5359
5360         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5361                 return False;
5362
5363         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5364                 ok = True;
5365
5366         t = gmtime(&now);
5367         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5368
5369         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5370                 ok = True;
5371
5372         free_a_printer(&printer, 2);
5373
5374         if (!ok)
5375                 errno = EACCES;
5376
5377         return ok;
5378 }
5379
5380 /****************************************************************************
5381  Fill in the servername sent in the _spoolss_open_printer_ex() call
5382 ****************************************************************************/
5383
5384 char* get_server_name( Printer_entry *printer )
5385 {
5386         return printer->servername;
5387 }
5388
5389