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