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