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