r8066: * had to modify the printer data storage slightly in ntprinters.tdb
[gd/samba/.git] / source / printing / nt_printing.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2000.
6  *  Copyright (C) Gerald Carter                2002-2003.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include "includes.h"
24
25 extern struct current_user current_user;
26
27 static TDB_CONTEXT *tdb_forms; /* used for forms files */
28 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29 static TDB_CONTEXT *tdb_printers; /* used for printers files */
30
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
37  
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
41 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
42  
43 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_4
44
45 /* Map generic permissions to printer object specific permissions */
46
47 GENERIC_MAPPING printer_generic_mapping = {
48         PRINTER_READ,
49         PRINTER_WRITE,
50         PRINTER_EXECUTE,
51         PRINTER_ALL_ACCESS
52 };
53
54 STANDARD_MAPPING printer_std_mapping = {
55         PRINTER_READ,
56         PRINTER_WRITE,
57         PRINTER_EXECUTE,
58         PRINTER_ALL_ACCESS
59 };
60
61 /* Map generic permissions to print server object specific permissions */
62
63 GENERIC_MAPPING printserver_generic_mapping = {
64         SERVER_READ,
65         SERVER_WRITE,
66         SERVER_EXECUTE,
67         SERVER_ALL_ACCESS
68 };
69
70 STANDARD_MAPPING printserver_std_mapping = {
71         SERVER_READ,
72         SERVER_WRITE,
73         SERVER_EXECUTE,
74         SERVER_ALL_ACCESS
75 };
76
77 /* We need one default form to support our default printer. Msoft adds the
78 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
79 array index). Letter is always first, so (for the current code) additions
80 always put things in the correct order. */
81 static const nt_forms_struct default_forms[] = {
82         {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83         {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
84         {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
85         {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
86         {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
87         {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
88         {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
89         {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
90         {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91         {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
92         {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
93         {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
94         {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
95         {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
96         {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
97         {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
98         {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
99         {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
100         {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
101         {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
102         {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
103         {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
104         {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
105         {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
106         {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
107         {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
108         {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
109         {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
110         {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
111         {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
112         {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
113         {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
114         {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
115         {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
116         {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
117         {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
118         {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
119         {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
120         {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
121         {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
122         {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
123         {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
124         {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
125         {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
126         {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
127         {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
128         {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
129         {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130         {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
131         {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
132         {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
133         {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
134         {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
135         {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
136         {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
137         {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
138         {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
139         {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
140         {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
141         {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
142         {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
143         {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
144         {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
145         {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
146         {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
147         {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
148         {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
149         {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
150         {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
151         {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
152         {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
153         {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
154         {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
155         {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
156         {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
157         {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
158         {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
159         {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
160         {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
161         {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
162         {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
163         {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
164         {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
165         {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
166         {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
167         {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
168         {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
169         {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
170         {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
171         {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
172         {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
173         {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
174         {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
175         {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
176         {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
177         {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
178         {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
179         {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
180         {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
181         {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
182         {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
183         {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
184         {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
185         {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
186         {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
187         {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
188         {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
189         {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
190         {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
191         {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
192         {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
193         {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
194         {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
195         {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
196         {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
197         {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
198         {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
199         {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
200 };
201
202 struct table_node {
203         const char      *long_archi;
204         const char      *short_archi;
205         int     version;
206 };
207  
208 #define SPL_ARCH_WIN40          "WIN40"
209 #define SPL_ARCH_W32X86         "W32X86"
210 #define SPL_ARCH_W32MIPS        "W32MIPS"
211 #define SPL_ARCH_W32ALPHA       "W32ALPHA"
212 #define SPL_ARCH_W32PPC         "W32PPC"
213 #define SPL_ARCH_IA64           "IA64"
214 #define SPL_ARCH_X64            "x64"
215
216 static const struct table_node archi_table[]= {
217
218         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
219         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
220         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
221         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
222         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
223         {"Windows IA64",         SPL_ARCH_IA64,         3 },
224         {"Windows x64",          SPL_ARCH_X64,          3 },
225         {NULL,                   "",            -1 }
226 };
227
228 static BOOL upgrade_to_version_3(void)
229 {
230         TDB_DATA kbuf, newkey, dbuf;
231  
232         DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
233  
234         for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
235                         newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
236
237                 dbuf = tdb_fetch(tdb_drivers, kbuf);
238
239                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
240                         DEBUG(0,("upgrade_to_version_3:moving form\n"));
241                         if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
242                                 SAFE_FREE(dbuf.dptr);
243                                 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
244                                 return False;
245                         }
246                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
247                                 SAFE_FREE(dbuf.dptr);
248                                 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
249                                 return False;
250                         }
251                 }
252  
253                 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
254                         DEBUG(0,("upgrade_to_version_3:moving printer\n"));
255                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
256                                 SAFE_FREE(dbuf.dptr);
257                                 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
258                                 return False;
259                         }
260                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
261                                 SAFE_FREE(dbuf.dptr);
262                                 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
263                                 return False;
264                         }
265                 }
266  
267                 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
268                         DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
269                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
270                                 SAFE_FREE(dbuf.dptr);
271                                 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
272                                 return False;
273                         }
274                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
275                                 SAFE_FREE(dbuf.dptr);
276                                 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
277                                 return False;
278                         }
279                 }
280  
281                 SAFE_FREE(dbuf.dptr);
282         }
283
284         return True;
285 }
286
287 /*******************************************************************
288  Fix an issue with security descriptors.  Printer sec_desc must 
289  use more than the generic bits that were previously used 
290  in <= 3.0.14a.  They must also have a owner and group SID assigned.
291  Otherwise, any printers than have been migrated to a Windows 
292  host using printmig.exe will not be accessible.
293 *******************************************************************/
294
295 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
296                             TDB_DATA data, void *state )
297 {
298         prs_struct ps;
299         SEC_DESC_BUF *sd_orig = NULL;
300         SEC_DESC_BUF *sd_new, *sd_store;
301         SEC_DESC *sec, *new_sec;
302         TALLOC_CTX *ctx = state;
303         int result, i;
304         uint32 sd_size, size_new_sec;
305         DOM_SID sid;
306
307         if (!data.dptr || data.dsize == 0)
308                 return 0;
309
310         if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 )
311                 return 0;
312
313         /* upgrade the security descriptor */
314
315         ZERO_STRUCT( ps );
316
317         prs_init( &ps, 0, ctx, UNMARSHALL );
318         prs_give_memory( &ps, data.dptr, data.dsize, True );
319
320         if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
321                 /* delete bad entries */
322                 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si.  Deleting....\n", key.dptr ));
323                 tdb_delete( tdb_printers, key );
324                 return 0;
325         }
326
327         sec = sd_orig->sec;
328                 
329         /* is this even valid? */
330         
331         if ( !sec->dacl )
332                 return 0;
333                 
334         /* update access masks */
335         
336         for ( i=0; i<sec->dacl->num_aces; i++ ) {
337                 switch ( sec->dacl->ace[i].info.mask ) {
338                         case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
339                                 sec->dacl->ace[i].info.mask = PRINTER_ACE_PRINT;
340                                 break;
341                                 
342                         case GENERIC_ALL_ACCESS:
343                                 sec->dacl->ace[i].info.mask = PRINTER_ACE_FULL_CONTROL;
344                                 break;
345                                 
346                         case READ_CONTROL_ACCESS:
347                                 sec->dacl->ace[i].info.mask = PRINTER_ACE_MANAGE_DOCUMENTS;
348                         
349                         default:        /* no change */
350                                 break;
351                 }
352         }
353
354         /* create a new SEC_DESC with the appropriate owner and group SIDs */
355
356         string_to_sid(&sid, "S-1-5-32-544" );
357         new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
358                 &sid, &sid,
359                 NULL, NULL, &size_new_sec );
360         sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
361
362         if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
363                 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
364                 return 0;
365         }
366         
367         /* store it back */
368         
369         sd_size = sec_desc_size(sd_store->sec) + sizeof(SEC_DESC_BUF);
370         prs_init(&ps, sd_size, ctx, MARSHALL);
371
372         if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
373                 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
374                 return 0;
375         }
376
377         data.dptr = prs_data_p( &ps );
378         data.dsize = sd_size;
379         
380         result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
381
382         prs_mem_free( &ps );
383         
384         /* 0 to continue and non-zero to stop traversal */
385
386         return (result == -1);
387 }
388
389 /*******************************************************************
390 *******************************************************************/
391
392 static BOOL upgrade_to_version_4(void)
393 {
394         TALLOC_CTX *ctx;
395         int result;
396
397         DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
398
399         if ( !(ctx = talloc_init( "upgrade_to_version_4" )) ) 
400                 return False;
401
402         result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
403
404         talloc_destroy( ctx );
405
406         return ( result != -1 );
407 }
408
409 /****************************************************************************
410  Open the NT printing tdbs. Done once before fork().
411 ****************************************************************************/
412
413 BOOL nt_printing_init(void)
414 {
415         const char *vstring = "INFO/version";
416         WERROR win_rc;
417         uint32 vers_id;
418
419         if ( tdb_drivers && tdb_printers && tdb_forms )
420                 return True;
421  
422         if (tdb_drivers)
423                 tdb_close(tdb_drivers);
424         tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
425         if (!tdb_drivers) {
426                 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
427                         lock_path("ntdrivers.tdb"), strerror(errno) ));
428                 return False;
429         }
430  
431         if (tdb_printers)
432                 tdb_close(tdb_printers);
433         tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
434         if (!tdb_printers) {
435                 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
436                         lock_path("ntprinters.tdb"), strerror(errno) ));
437                 return False;
438         }
439  
440         if (tdb_forms)
441                 tdb_close(tdb_forms);
442         tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
443         if (!tdb_forms) {
444                 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
445                         lock_path("ntforms.tdb"), strerror(errno) ));
446                 return False;
447         }
448  
449         /* handle a Samba upgrade */
450         tdb_lock_bystring(tdb_drivers, vstring, 0);
451
452         /* ---------------- Start Lock Region ---------------- */
453
454         /* Cope with byte-reversed older versions of the db. */
455         vers_id = tdb_fetch_int32(tdb_drivers, vstring);
456
457         if ( vers_id != NTDRIVERS_DATABASE_VERSION ) {
458
459                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
460                         /* Written on a bigendian machine with old fetch_int code. Save as le. */
461                         /* The only upgrade between V2 and V3 is to save the version in little-endian. */
462                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
463                         vers_id = NTDRIVERS_DATABASE_VERSION_3;
464                 }
465
466                 if (vers_id != NTDRIVERS_DATABASE_VERSION_3 ) {
467         
468                         if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) { 
469                                 if (!upgrade_to_version_3())
470                                         return False;
471                         } else
472                                 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
473                          
474                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
475                 }
476
477                 /* at this point we know that the database is at version 3 so upgrade to v4 */
478
479                 if ( !upgrade_to_version_4() )
480                         return False;
481                 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
482         }
483
484         /* ---------------- End Lock Region ------------------ */
485
486         tdb_unlock_bystring(tdb_drivers, vstring);
487
488         update_c_setprinter(True);
489
490         /*
491          * register callback to handle updating printers as new
492          * drivers are installed
493          */
494
495         message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
496
497         /*
498          * register callback to handle updating printer data
499          * when a driver is initialized
500          */
501
502         message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
503
504         /*
505          * register callback to handle invalidating the printer cache 
506          * between smbd processes.
507          */
508
509         message_register( MSG_PRINTER_MOD, receive_printer_mod_msg);
510
511         /* of course, none of the message callbacks matter if you don't
512            tell messages.c that you interested in receiving PRINT_GENERAL 
513            msgs.  This is done in claim_connection() */
514
515
516         if ( lp_security() == SEC_ADS ) {
517                 win_rc = check_published_printers();
518                 if (!W_ERROR_IS_OK(win_rc))
519                         DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
520         }
521
522         return True;
523 }
524
525 /*******************************************************************
526  Function to allow filename parsing "the old way".
527 ********************************************************************/
528
529 static BOOL driver_unix_convert(char *name,connection_struct *conn,
530                 char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
531 {
532         unix_format(name);
533         unix_clean_name(name);
534         trim_string(name,"/","/");
535         return unix_convert(name, conn, saved_last_component, bad_path, pst);
536 }
537
538 /*******************************************************************
539  tdb traversal function for counting printers.
540 ********************************************************************/
541
542 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
543                                       TDB_DATA data, void *context)
544 {
545         int *printer_count = (int*)context;
546  
547         if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
548                 (*printer_count)++;
549                 DEBUG(10,("traverse_counting_printers: printer = [%s]  printer_count = %d\n", key.dptr, *printer_count));
550         }
551  
552         return 0;
553 }
554  
555 /*******************************************************************
556  Update the spooler global c_setprinter. This variable is initialized
557  when the parent smbd starts with the number of existing printers. It
558  is monotonically increased by the current number of printers *after*
559  each add or delete printer RPC. Only Microsoft knows why... JRR020119
560 ********************************************************************/
561
562 uint32 update_c_setprinter(BOOL initialize)
563 {
564         int32 c_setprinter;
565         int32 printer_count = 0;
566  
567         tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
568  
569         /* Traverse the tdb, counting the printers */
570         tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
571  
572         /* If initializing, set c_setprinter to current printers count
573          * otherwise, bump it by the current printer count
574          */
575         if (!initialize)
576                 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
577         else
578                 c_setprinter = printer_count;
579  
580         DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
581         tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
582  
583         tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
584  
585         return (uint32)c_setprinter;
586 }
587
588 /*******************************************************************
589  Get the spooler global c_setprinter, accounting for initialization.
590 ********************************************************************/
591
592 uint32 get_c_setprinter(void)
593 {
594         int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
595  
596         if (c_setprinter == (int32)-1)
597                 c_setprinter = update_c_setprinter(True);
598  
599         DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
600  
601         return (uint32)c_setprinter;
602 }
603
604 /****************************************************************************
605  Get builtin form struct list.
606 ****************************************************************************/
607
608 int get_builtin_ntforms(nt_forms_struct **list)
609 {
610         *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
611         return sizeof(default_forms) / sizeof(default_forms[0]);
612 }
613
614 /****************************************************************************
615  get a builtin form struct
616 ****************************************************************************/
617
618 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
619 {
620         int i,count;
621         fstring form_name;
622         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
623         DEBUGADD(6,("Looking for builtin form %s \n", form_name));
624         count = sizeof(default_forms) / sizeof(default_forms[0]);
625         for (i=0;i<count;i++) {
626                 if (strequal(form_name,default_forms[i].name)) {
627                         DEBUGADD(6,("Found builtin form %s \n", form_name));
628                         memcpy(form,&default_forms[i],sizeof(*form));
629                         break;
630                 }
631         }
632
633         return (i !=count);
634 }
635
636 /****************************************************************************
637 get a form struct list
638 ****************************************************************************/
639 int get_ntforms(nt_forms_struct **list)
640 {
641         TDB_DATA kbuf, newkey, dbuf;
642         nt_forms_struct *tl;
643         nt_forms_struct form;
644         int ret;
645         int i;
646         int n = 0;
647
648         for (kbuf = tdb_firstkey(tdb_forms);
649              kbuf.dptr;
650              newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) 
651         {
652                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) 
653                         continue;
654                 
655                 dbuf = tdb_fetch(tdb_forms, kbuf);
656                 if (!dbuf.dptr) 
657                         continue;
658
659                 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
660                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
661                                  &i, &form.flag, &form.width, &form.length, &form.left,
662                                  &form.top, &form.right, &form.bottom);
663                 SAFE_FREE(dbuf.dptr);
664                 if (ret != dbuf.dsize) 
665                         continue;
666
667                 tl = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
668                 if (!tl) {
669                         DEBUG(0,("get_ntforms: Realloc fail.\n"));
670                         return 0;
671                 }
672                 *list = tl;
673                 (*list)[n] = form;
674                 n++;
675         }
676         
677
678         return n;
679 }
680
681 /****************************************************************************
682 write a form struct list
683 ****************************************************************************/
684 int write_ntforms(nt_forms_struct **list, int number)
685 {
686         pstring buf, key;
687         int len;
688         TDB_DATA kbuf,dbuf;
689         int i;
690
691         for (i=0;i<number;i++) {
692                 /* save index, so list is rebuilt in correct order */
693                 len = tdb_pack(buf, sizeof(buf), "dddddddd",
694                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
695                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
696                                (*list)[i].bottom);
697                 if (len > sizeof(buf)) break;
698                 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
699                 kbuf.dsize = strlen(key)+1;
700                 kbuf.dptr = key;
701                 dbuf.dsize = len;
702                 dbuf.dptr = buf;
703                 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
704        }
705
706        return i;
707 }
708
709 /****************************************************************************
710 add a form struct at the end of the list
711 ****************************************************************************/
712 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
713 {
714         int n=0;
715         BOOL update;
716         fstring form_name;
717         nt_forms_struct *tl;
718
719         /*
720          * NT tries to add forms even when
721          * they are already in the base
722          * only update the values if already present
723          */
724
725         update=False;
726         
727         unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
728         for (n=0; n<*count; n++) {
729                 if ( strequal((*list)[n].name, form_name) ) {
730                         update=True;
731                         break;
732                 }
733         }
734
735         if (update==False) {
736                 if((tl=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
737                         DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
738                         return False;
739                 }
740                 *list = tl;
741                 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
742                 (*count)++;
743         }
744         
745         (*list)[n].flag=form->flags;
746         (*list)[n].width=form->size_x;
747         (*list)[n].length=form->size_y;
748         (*list)[n].left=form->left;
749         (*list)[n].top=form->top;
750         (*list)[n].right=form->right;
751         (*list)[n].bottom=form->bottom;
752
753         DEBUG(6,("add_a_form: Successfully %s form [%s]\n", 
754                 update ? "updated" : "added", form_name));
755
756         return True;
757 }
758
759 /****************************************************************************
760  Delete a named form struct.
761 ****************************************************************************/
762
763 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
764 {
765         pstring key;
766         TDB_DATA kbuf;
767         int n=0;
768         fstring form_name;
769
770         *ret = WERR_OK;
771
772         unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
773
774         for (n=0; n<*count; n++) {
775                 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
776                         DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
777                         break;
778                 }
779         }
780
781         if (n == *count) {
782                 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
783                 *ret = WERR_INVALID_PARAM;
784                 return False;
785         }
786
787         slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
788         kbuf.dsize = strlen(key)+1;
789         kbuf.dptr = key;
790         if (tdb_delete(tdb_forms, kbuf) != 0) {
791                 *ret = WERR_NOMEM;
792                 return False;
793         }
794
795         return True;
796 }
797
798 /****************************************************************************
799  Update a form struct.
800 ****************************************************************************/
801
802 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
803 {
804         int n=0;
805         fstring form_name;
806         unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
807
808         DEBUG(106, ("[%s]\n", form_name));
809         for (n=0; n<count; n++) {
810                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
811                 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
812                         break;
813         }
814
815         if (n==count) return;
816
817         (*list)[n].flag=form->flags;
818         (*list)[n].width=form->size_x;
819         (*list)[n].length=form->size_y;
820         (*list)[n].left=form->left;
821         (*list)[n].top=form->top;
822         (*list)[n].right=form->right;
823         (*list)[n].bottom=form->bottom;
824 }
825
826 /****************************************************************************
827  Get the nt drivers list.
828  Traverse the database and look-up the matching names.
829 ****************************************************************************/
830 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
831 {
832         int total=0;
833         const char *short_archi;
834         fstring *fl;
835         pstring key;
836         TDB_DATA kbuf, newkey;
837
838         short_archi = get_short_archi(architecture);
839         slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
840
841         for (kbuf = tdb_firstkey(tdb_drivers);
842              kbuf.dptr;
843              newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
844
845                 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
846                         continue;
847                 
848                 if((fl = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
849                         DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
850                         return -1;
851                 }
852                 else *list = fl;
853
854                 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
855                 total++;
856         }
857
858         return(total);
859 }
860
861 /****************************************************************************
862 function to do the mapping between the long architecture name and
863 the short one.
864 ****************************************************************************/
865 const char *get_short_archi(const char *long_archi)
866 {
867         int i=-1;
868
869         DEBUG(107,("Getting architecture dependant directory\n"));
870         do {
871                 i++;
872         } while ( (archi_table[i].long_archi!=NULL ) &&
873                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
874
875         if (archi_table[i].long_archi==NULL) {
876                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
877                 return NULL;
878         }
879
880         /* this might be client code - but shouldn't this be an fstrcpy etc? */
881
882
883         DEBUGADD(108,("index: [%d]\n", i));
884         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
885         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
886
887         return archi_table[i].short_archi;
888 }
889
890 /****************************************************************************
891  Version information in Microsoft files is held in a VS_VERSION_INFO structure.
892  There are two case to be covered here: PE (Portable Executable) and NE (New
893  Executable) files. Both files support the same INFO structure, but PE files
894  store the signature in unicode, and NE files store it as !unicode.
895  returns -1 on error, 1 on version info found, and 0 on no version info found.
896 ****************************************************************************/
897
898 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
899 {
900         int     i;
901         char    *buf = NULL;
902         ssize_t byte_count;
903
904         if ((buf=SMB_MALLOC(PE_HEADER_SIZE)) == NULL) {
905                 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
906                                 fname, PE_HEADER_SIZE));
907                 goto error_exit;
908         }
909
910         /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
911         if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
912                 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
913                          fname, (unsigned long)byte_count));
914                 goto no_version_info;
915         }
916
917         /* Is this really a DOS header? */
918         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
919                 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
920                                 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
921                 goto no_version_info;
922         }
923
924         /* Skip OEM header (if any) and the DOS stub to start of Windows header */
925         if (SMB_VFS_LSEEK(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
926                 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
927                                 fname, errno));
928                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
929                 goto no_version_info;
930         }
931
932         if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
933                 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
934                          fname, (unsigned long)byte_count));
935                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
936                 goto no_version_info;
937         }
938
939         /* The header may be a PE (Portable Executable) or an NE (New Executable) */
940         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
941                 unsigned int num_sections;
942                 unsigned int section_table_bytes;
943                 
944                 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
945                         DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
946                                         fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
947                         /* At this point, we assume the file is in error. It still could be somthing
948                          * else besides a PE file, but it unlikely at this point.
949                          */
950                         goto error_exit;
951                 }
952
953                 /* get the section table */
954                 num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
955                 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
956                 if (section_table_bytes == 0)
957                         goto error_exit;
958
959                 SAFE_FREE(buf);
960                 if ((buf=SMB_MALLOC(section_table_bytes)) == NULL) {
961                         DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
962                                         fname, section_table_bytes));
963                         goto error_exit;
964                 }
965
966                 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
967                         DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
968                                  fname, (unsigned long)byte_count));
969                         goto error_exit;
970                 }
971
972                 /* Iterate the section table looking for the resource section ".rsrc" */
973                 for (i = 0; i < num_sections; i++) {
974                         int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
975
976                         if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
977                                 unsigned int section_pos   = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
978                                 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
979
980                                 if (section_bytes == 0)
981                                         goto error_exit;
982
983                                 SAFE_FREE(buf);
984                                 if ((buf=SMB_MALLOC(section_bytes)) == NULL) {
985                                         DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
986                                                         fname, section_bytes));
987                                         goto error_exit;
988                                 }
989
990                                 /* Seek to the start of the .rsrc section info */
991                                 if (SMB_VFS_LSEEK(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
992                                         DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
993                                                         fname, errno));
994                                         goto error_exit;
995                                 }
996
997                                 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
998                                         DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
999                                                  fname, (unsigned long)byte_count));
1000                                         goto error_exit;
1001                                 }
1002
1003                                 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1004                                         goto error_exit;
1005
1006                                 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1007                                         /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1008                                         if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1009                                                 /* Align to next long address */
1010                                                 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1011
1012                                                 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1013                                                         *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1014                                                         *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1015                                                         
1016                                                         DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1017                                                                           fname, *major, *minor,
1018                                                                           (*major>>16)&0xffff, *major&0xffff,
1019                                                                           (*minor>>16)&0xffff, *minor&0xffff));
1020                                                         SAFE_FREE(buf);
1021                                                         return 1;
1022                                                 }
1023                                         }
1024                                 }
1025                         }
1026                 }
1027
1028                 /* Version info not found, fall back to origin date/time */
1029                 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1030                 SAFE_FREE(buf);
1031                 return 0;
1032
1033         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1034                 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1035                         DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1036                                         fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1037                         /* At this point, we assume the file is in error. It still could be somthing
1038                          * else besides a NE file, but it unlikely at this point. */
1039                         goto error_exit;
1040                 }
1041
1042                 /* Allocate a bit more space to speed up things */
1043                 SAFE_FREE(buf);
1044                 if ((buf=SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1045                         DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes  = %d\n",
1046                                         fname, PE_HEADER_SIZE));
1047                         goto error_exit;
1048                 }
1049
1050                 /* This is a HACK! I got tired of trying to sort through the messy
1051                  * 'NE' file format. If anyone wants to clean this up please have at
1052                  * it, but this works. 'NE' files will eventually fade away. JRR */
1053                 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1054                         /* Cover case that should not occur in a well formed 'NE' .dll file */
1055                         if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1056
1057                         for(i=0; i<byte_count; i++) {
1058                                 /* Fast skip past data that can't possibly match */
1059                                 if (buf[i] != 'V') continue;
1060
1061                                 /* Potential match data crosses buf boundry, move it to beginning
1062                                  * of buf, and fill the buf with as much as it will hold. */
1063                                 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1064                                         int bc;
1065
1066                                         memcpy(buf, &buf[i], byte_count-i);
1067                                         if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1068                                                                    (byte_count-i))) < 0) {
1069
1070                                                 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1071                                                                  fname, errno));
1072                                                 goto error_exit;
1073                                         }
1074
1075                                         byte_count = bc + (byte_count - i);
1076                                         if (byte_count<VS_VERSION_INFO_SIZE) break;
1077
1078                                         i = 0;
1079                                 }
1080
1081                                 /* Check that the full signature string and the magic number that
1082                                  * follows exist (not a perfect solution, but the chances that this
1083                                  * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1084                                  * twice, as it is simpler to read the code. */
1085                                 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1086                                         /* Compute skip alignment to next long address */
1087                                         int skip = -(SMB_VFS_LSEEK(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
1088                                                                  sizeof(VS_SIGNATURE)) & 3;
1089                                         if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1090
1091                                         *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1092                                         *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1093                                         DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1094                                                           fname, *major, *minor,
1095                                                           (*major>>16)&0xffff, *major&0xffff,
1096                                                           (*minor>>16)&0xffff, *minor&0xffff));
1097                                         SAFE_FREE(buf);
1098                                         return 1;
1099                                 }
1100                         }
1101                 }
1102
1103                 /* Version info not found, fall back to origin date/time */
1104                 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1105                 SAFE_FREE(buf);
1106                 return 0;
1107
1108         } else
1109                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1110                 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1111                                 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1112
1113         no_version_info:
1114                 SAFE_FREE(buf);
1115                 return 0;
1116
1117         error_exit:
1118                 SAFE_FREE(buf);
1119                 return -1;
1120 }
1121
1122 /****************************************************************************
1123 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1124 share one or more files. During the MS installation process files are checked
1125 to insure that only a newer version of a shared file is installed over an
1126 older version. There are several possibilities for this comparison. If there
1127 is no previous version, the new one is newer (obviously). If either file is
1128 missing the version info structure, compare the creation date (on Unix use
1129 the modification date). Otherwise chose the numerically larger version number.
1130 ****************************************************************************/
1131
1132 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1133 {
1134         BOOL   use_version = True;
1135         pstring filepath;
1136
1137         uint32 new_major;
1138         uint32 new_minor;
1139         time_t new_create_time;
1140
1141         uint32 old_major;
1142         uint32 old_minor;
1143         time_t old_create_time;
1144
1145         int access_mode;
1146         int action;
1147         files_struct    *fsp = NULL;
1148         SMB_STRUCT_STAT st;
1149         SMB_STRUCT_STAT stat_buf;
1150         BOOL bad_path;
1151
1152         SET_STAT_INVALID(st);
1153         SET_STAT_INVALID(stat_buf);
1154         new_create_time = (time_t)0;
1155         old_create_time = (time_t)0;
1156
1157         /* Get file version info (if available) for previous file (if it exists) */
1158         pstrcpy(filepath, old_file);
1159
1160         driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1161
1162         fsp = open_file_shared(conn, filepath, &stat_buf,
1163                                                    SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1164                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1165                                                    FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1166         if (!fsp) {
1167                 /* Old file not found, so by definition new file is in fact newer */
1168                 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1169                                 filepath, errno));
1170                 return True;
1171
1172         } else {
1173                 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1174                 if (ret == -1) goto error_exit;
1175
1176                 if (!ret) {
1177                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1178                                          old_file));
1179                         use_version = False;
1180                         if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1181                         old_create_time = st.st_mtime;
1182                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1183                 }
1184         }
1185         close_file(fsp, True);
1186
1187         /* Get file version info (if available) for new file */
1188         pstrcpy(filepath, new_file);
1189         driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1190
1191         fsp = open_file_shared(conn, filepath, &stat_buf,
1192                                                    SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1193                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1194                                                    FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1195         if (!fsp) {
1196                 /* New file not found, this shouldn't occur if the caller did its job */
1197                 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1198                                 filepath, errno));
1199                 goto error_exit;
1200
1201         } else {
1202                 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1203                 if (ret == -1) goto error_exit;
1204
1205                 if (!ret) {
1206                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1207                                          new_file));
1208                         use_version = False;
1209                         if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1210                         new_create_time = st.st_mtime;
1211                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1212                 }
1213         }
1214         close_file(fsp, True);
1215
1216         if (use_version && (new_major != old_major || new_minor != old_minor)) {
1217                 /* Compare versions and choose the larger version number */
1218                 if (new_major > old_major ||
1219                         (new_major == old_major && new_minor > old_minor)) {
1220                         
1221                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1222                         return True;
1223                 }
1224                 else {
1225                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1226                         return False;
1227                 }
1228
1229         } else {
1230                 /* Compare modification time/dates and choose the newest time/date */
1231                 if (new_create_time > old_create_time) {
1232                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1233                         return True;
1234                 }
1235                 else {
1236                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1237                         return False;
1238                 }
1239         }
1240
1241         error_exit:
1242                 if(fsp)
1243                         close_file(fsp, True);
1244                 return -1;
1245 }
1246
1247 /****************************************************************************
1248 Determine the correct cVersion associated with an architecture and driver
1249 ****************************************************************************/
1250 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1251                                    struct current_user *user, WERROR *perr)
1252 {
1253         int               cversion;
1254         int               access_mode;
1255         int               action;
1256         NTSTATUS          nt_status;
1257         pstring           driverpath;
1258         DATA_BLOB         null_pw;
1259         fstring           res_type;
1260         files_struct      *fsp = NULL;
1261         BOOL              bad_path;
1262         SMB_STRUCT_STAT   st;
1263         connection_struct *conn;
1264
1265         SET_STAT_INVALID(st);
1266
1267         *perr = WERR_INVALID_PARAM;
1268
1269         /* If architecture is Windows 95/98/ME, the version is always 0. */
1270         if (strcmp(architecture, "WIN40") == 0) {
1271                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1272                 *perr = WERR_OK;
1273                 return 0;
1274         }
1275
1276         /*
1277          * Connect to the print$ share under the same account as the user connected
1278          * to the rpc pipe. Note we must still be root to do this.
1279          */
1280
1281         /* Null password is ok - we are already an authenticated user... */
1282         null_pw = data_blob(NULL, 0);
1283         fstrcpy(res_type, "A:");
1284         become_root();
1285         conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1286         unbecome_root();
1287
1288         if (conn == NULL) {
1289                 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1290                 *perr = ntstatus_to_werror(nt_status);
1291                 return -1;
1292         }
1293
1294         /* We are temporarily becoming the connection user. */
1295         if (!become_user(conn, user->vuid)) {
1296                 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1297                 *perr = WERR_ACCESS_DENIED;
1298                 return -1;
1299         }
1300
1301         /* Open the driver file (Portable Executable format) and determine the
1302          * deriver the cversion. */
1303         slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1304
1305         driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
1306
1307         if ( !vfs_file_exist( conn, driverpath, &st ) ) {
1308                 *perr = WERR_BADFILE;
1309                 goto error_exit;
1310         }
1311
1312         fsp = open_file_shared(conn, driverpath, &st,
1313                 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1314                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1315                 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1316
1317         if (!fsp) {
1318                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1319                                 driverpath, errno));
1320                 *perr = WERR_ACCESS_DENIED;
1321                 goto error_exit;
1322         }
1323         else {
1324                 uint32 major;
1325                 uint32 minor;
1326                 int    ret = get_file_version(fsp, driverpath, &major, &minor);
1327                 if (ret == -1) goto error_exit;
1328
1329                 if (!ret) {
1330                         DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1331                         goto error_exit;
1332                 }
1333
1334                 /*
1335                  * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1336                  * for more details. Version in this case is not just the version of the 
1337                  * file, but the version in the sense of kernal mode (2) vs. user mode
1338                  * (3) drivers. Other bits of the version fields are the version info. 
1339                  * JRR 010716
1340                 */
1341                 cversion = major & 0x0000ffff;
1342                 switch (cversion) {
1343                         case 2: /* WinNT drivers */
1344                         case 3: /* Win2K drivers */
1345                                 break;
1346                         
1347                         default:
1348                                 DEBUG(6,("get_correct_cversion: cversion invalid [%s]  cversion = %d\n", 
1349                                         driverpath, cversion));
1350                                 goto error_exit;
1351                 }
1352
1353                 DEBUG(10,("get_correct_cversion: Version info found [%s]  major = 0x%x  minor = 0x%x\n",
1354                                   driverpath, major, minor));
1355         }
1356
1357         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1358                 driverpath, cversion));
1359
1360         close_file(fsp, True);
1361         close_cnum(conn, user->vuid);
1362         unbecome_user();
1363         *perr = WERR_OK;
1364         return cversion;
1365
1366
1367   error_exit:
1368
1369         if(fsp)
1370                 close_file(fsp, True);
1371
1372         close_cnum(conn, user->vuid);
1373         unbecome_user();
1374         return -1;
1375 }
1376
1377 /****************************************************************************
1378 ****************************************************************************/
1379 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1380                                                                                          struct current_user *user)
1381 {
1382         const char *architecture;
1383         fstring new_name;
1384         char *p;
1385         int i;
1386         WERROR err;
1387
1388         /* clean up the driver name.
1389          * we can get .\driver.dll
1390          * or worse c:\windows\system\driver.dll !
1391          */
1392         /* using an intermediate string to not have overlaping memcpy()'s */
1393         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1394                 fstrcpy(new_name, p+1);
1395                 fstrcpy(driver->driverpath, new_name);
1396         }
1397
1398         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1399                 fstrcpy(new_name, p+1);
1400                 fstrcpy(driver->datafile, new_name);
1401         }
1402
1403         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1404                 fstrcpy(new_name, p+1);
1405                 fstrcpy(driver->configfile, new_name);
1406         }
1407
1408         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1409                 fstrcpy(new_name, p+1);
1410                 fstrcpy(driver->helpfile, new_name);
1411         }
1412
1413         if (driver->dependentfiles) {
1414                 for (i=0; *driver->dependentfiles[i]; i++) {
1415                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1416                                 fstrcpy(new_name, p+1);
1417                                 fstrcpy(driver->dependentfiles[i], new_name);
1418                         }
1419                 }
1420         }
1421
1422         architecture = get_short_archi(driver->environment);
1423         
1424         /* jfm:7/16/2000 the client always sends the cversion=0.
1425          * The server should check which version the driver is by reading
1426          * the PE header of driver->driverpath.
1427          *
1428          * For Windows 95/98 the version is 0 (so the value sent is correct)
1429          * For Windows NT (the architecture doesn't matter)
1430          *      NT 3.1: cversion=0
1431          *      NT 3.5/3.51: cversion=1
1432          *      NT 4: cversion=2
1433          *      NT2K: cversion=3
1434          */
1435         if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1436                         return err;
1437
1438         return WERR_OK;
1439 }
1440         
1441 /****************************************************************************
1442 ****************************************************************************/
1443 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1444 {
1445         const char *architecture;
1446         fstring new_name;
1447         char *p;
1448         int i;
1449         WERROR err;
1450
1451         /* clean up the driver name.
1452          * we can get .\driver.dll
1453          * or worse c:\windows\system\driver.dll !
1454          */
1455         /* using an intermediate string to not have overlaping memcpy()'s */
1456         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1457                 fstrcpy(new_name, p+1);
1458                 fstrcpy(driver->driverpath, new_name);
1459         }
1460
1461         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1462                 fstrcpy(new_name, p+1);
1463                 fstrcpy(driver->datafile, new_name);
1464         }
1465
1466         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1467                 fstrcpy(new_name, p+1);
1468                 fstrcpy(driver->configfile, new_name);
1469         }
1470
1471         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1472                 fstrcpy(new_name, p+1);
1473                 fstrcpy(driver->helpfile, new_name);
1474         }
1475
1476         if (driver->dependentfiles) {
1477                 for (i=0; *driver->dependentfiles[i]; i++) {
1478                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1479                                 fstrcpy(new_name, p+1);
1480                                 fstrcpy(driver->dependentfiles[i], new_name);
1481                         }
1482                 }
1483         }
1484
1485         architecture = get_short_archi(driver->environment);
1486
1487         /* jfm:7/16/2000 the client always sends the cversion=0.
1488          * The server should check which version the driver is by reading
1489          * the PE header of driver->driverpath.
1490          *
1491          * For Windows 95/98 the version is 0 (so the value sent is correct)
1492          * For Windows NT (the architecture doesn't matter)
1493          *      NT 3.1: cversion=0
1494          *      NT 3.5/3.51: cversion=1
1495          *      NT 4: cversion=2
1496          *      NT2K: cversion=3
1497          */
1498
1499         if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1500                         return err;
1501
1502         return WERR_OK;
1503 }
1504
1505 /****************************************************************************
1506 ****************************************************************************/
1507 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1508                                                           uint32 level, struct current_user *user)
1509 {
1510         switch (level) {
1511                 case 3:
1512                 {
1513                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1514                         driver=driver_abstract.info_3;
1515                         return clean_up_driver_struct_level_3(driver, user);
1516                 }
1517                 case 6:
1518                 {
1519                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1520                         driver=driver_abstract.info_6;
1521                         return clean_up_driver_struct_level_6(driver, user);
1522                 }
1523                 default:
1524                         return WERR_INVALID_PARAM;
1525         }
1526 }
1527
1528 /****************************************************************************
1529  This function sucks and should be replaced. JRA.
1530 ****************************************************************************/
1531
1532 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1533 {
1534     dst->cversion  = src->version;
1535
1536     fstrcpy( dst->name, src->name);
1537     fstrcpy( dst->environment, src->environment);
1538     fstrcpy( dst->driverpath, src->driverpath);
1539     fstrcpy( dst->datafile, src->datafile);
1540     fstrcpy( dst->configfile, src->configfile);
1541     fstrcpy( dst->helpfile, src->helpfile);
1542     fstrcpy( dst->monitorname, src->monitorname);
1543     fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1544     dst->dependentfiles = src->dependentfiles;
1545 }
1546
1547 #if 0 /* Debugging function */
1548
1549 static char* ffmt(unsigned char *c){
1550         int i;
1551         static char ffmt_str[17];
1552
1553         for (i=0; i<16; i++) {
1554                 if ((c[i] < ' ') || (c[i] > '~'))
1555                         ffmt_str[i]='.';
1556                 else
1557                         ffmt_str[i]=c[i];
1558         }
1559     ffmt_str[16]='\0';
1560         return ffmt_str;
1561 }
1562
1563 #endif
1564
1565 /****************************************************************************
1566 ****************************************************************************/
1567 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, 
1568                                   struct current_user *user, WERROR *perr)
1569 {
1570         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1571         NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1572         const char *architecture;
1573         pstring new_dir;
1574         pstring old_name;
1575         pstring new_name;
1576         DATA_BLOB null_pw;
1577         connection_struct *conn;
1578         NTSTATUS nt_status;
1579         pstring inbuf;
1580         pstring outbuf;
1581         fstring res_type;
1582         BOOL bad_path;
1583         SMB_STRUCT_STAT st;
1584         int ver = 0;
1585         int i;
1586         int err;
1587
1588         memset(inbuf, '\0', sizeof(inbuf));
1589         memset(outbuf, '\0', sizeof(outbuf));
1590         *perr = WERR_OK;
1591
1592         if (level==3)
1593                 driver=driver_abstract.info_3;
1594         else if (level==6) {
1595                 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1596                 driver = &converted_driver;
1597         } else {
1598                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1599                 return WERR_UNKNOWN_LEVEL;
1600         }
1601
1602         architecture = get_short_archi(driver->environment);
1603
1604         /*
1605          * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1606          * Note we must be root to do this.
1607          */
1608
1609         null_pw = data_blob(NULL, 0);
1610         fstrcpy(res_type, "A:");
1611         become_root();
1612         conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1613         unbecome_root();
1614
1615         if (conn == NULL) {
1616                 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1617                 *perr = ntstatus_to_werror(nt_status);
1618                 return WERR_NO_SUCH_SHARE;
1619         }
1620
1621         /*
1622          * Save who we are - we are temporarily becoming the connection user.
1623          */
1624
1625         if (!become_user(conn, conn->vuid)) {
1626                 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1627                 return WERR_ACCESS_DENIED;
1628         }
1629
1630         /*
1631          * make the directories version and version\driver_name
1632          * under the architecture directory.
1633          */
1634         DEBUG(5,("Creating first directory\n"));
1635         slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1636         driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
1637         mkdir_internal(conn, new_dir, bad_path);
1638
1639         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1640          * listed for this driver which has already been moved, skip it (note:
1641          * drivers may list the same file name several times. Then check if the
1642          * file already exists in archi\cversion\, if so, check that the version
1643          * info (or time stamps if version info is unavailable) is newer (or the
1644          * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1645          * Otherwise, delete the file.
1646          *
1647          * If a file is not moved to archi\cversion\ because of an error, all the
1648          * rest of the 'unmoved' driver files are removed from archi\. If one or
1649          * more of the driver's files was already moved to archi\cversion\, it
1650          * potentially leaves the driver in a partially updated state. Version
1651          * trauma will most likely occur if an client attempts to use any printer
1652          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1653          * done is appropriate... later JRR
1654          */
1655
1656         DEBUG(5,("Moving files now !\n"));
1657
1658         if (driver->driverpath && strlen(driver->driverpath)) {
1659                 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);      
1660                 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);   
1661                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1662                         driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1663                         if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1664                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1665                                                 new_name, old_name));
1666                                 *perr = WERR_ACCESS_DENIED;
1667                                 ver = -1;
1668                         }
1669                 } 
1670         }
1671
1672         if (driver->datafile && strlen(driver->datafile)) {
1673                 if (!strequal(driver->datafile, driver->driverpath)) {
1674                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);        
1675                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);     
1676                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1677                                 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1678                                 if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1679                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1680                                                         new_name, old_name));
1681                                         *perr = WERR_ACCESS_DENIED;
1682                                         ver = -1;
1683                                 }
1684                         }
1685                 }
1686         }
1687
1688         if (driver->configfile && strlen(driver->configfile)) {
1689                 if (!strequal(driver->configfile, driver->driverpath) &&
1690                         !strequal(driver->configfile, driver->datafile)) {
1691                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);      
1692                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);   
1693                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1694                                 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1695                                 if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1696                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1697                                                         new_name, old_name));
1698                                         *perr = WERR_ACCESS_DENIED;
1699                                         ver = -1;
1700                                 }
1701                         }
1702                 }
1703         }
1704
1705         if (driver->helpfile && strlen(driver->helpfile)) {
1706                 if (!strequal(driver->helpfile, driver->driverpath) &&
1707                         !strequal(driver->helpfile, driver->datafile) &&
1708                         !strequal(driver->helpfile, driver->configfile)) {
1709                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);        
1710                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);     
1711                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1712                                 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1713                                 if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1714                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1715                                                         new_name, old_name));
1716                                         *perr = WERR_ACCESS_DENIED;
1717                                         ver = -1;
1718                                 }
1719                         }
1720                 }
1721         }
1722
1723         if (driver->dependentfiles) {
1724                 for (i=0; *driver->dependentfiles[i]; i++) {
1725                         if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1726                                 !strequal(driver->dependentfiles[i], driver->datafile) &&
1727                                 !strequal(driver->dependentfiles[i], driver->configfile) &&
1728                                 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1729                                 int j;
1730                                 for (j=0; j < i; j++) {
1731                                         if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1732                                                 goto NextDriver;
1733                                         }
1734                                 }
1735
1736                                 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);       
1737                                 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);    
1738                                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1739                                         driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1740                                         if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1741                                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1742                                                                 new_name, old_name));
1743                                                 *perr = WERR_ACCESS_DENIED;
1744                                                 ver = -1;
1745                                         }
1746                                 }
1747                         }
1748                 NextDriver: ;
1749                 }
1750         }
1751
1752         close_cnum(conn, user->vuid);
1753         unbecome_user();
1754
1755         return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
1756 }
1757
1758 /****************************************************************************
1759 ****************************************************************************/
1760 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1761 {
1762         int len, buflen;
1763         const char *architecture;
1764         pstring directory;
1765         fstring temp_name;
1766         pstring key;
1767         char *buf;
1768         int i, ret;
1769         TDB_DATA kbuf, dbuf;
1770
1771         architecture = get_short_archi(driver->environment);
1772
1773         /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1774          * \\server is added in the rpc server layer.
1775          * It does make sense to NOT store the server's name in the printer TDB.
1776          */
1777
1778         slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1779
1780         /* .inf files do not always list a file for each of the four standard files. 
1781          * Don't prepend a path to a null filename, or client claims:
1782          *   "The server on which the printer resides does not have a suitable 
1783          *   <printer driver name> printer driver installed. Click OK if you 
1784          *   wish to install the driver on your local machine."
1785          */
1786         if (strlen(driver->driverpath)) {
1787                 fstrcpy(temp_name, driver->driverpath);
1788                 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1789         }
1790
1791         if (strlen(driver->datafile)) {
1792                 fstrcpy(temp_name, driver->datafile);
1793                 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1794         }
1795
1796         if (strlen(driver->configfile)) {
1797                 fstrcpy(temp_name, driver->configfile);
1798                 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1799         }
1800
1801         if (strlen(driver->helpfile)) {
1802                 fstrcpy(temp_name, driver->helpfile);
1803                 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1804         }
1805
1806         if (driver->dependentfiles) {
1807                 for (i=0; *driver->dependentfiles[i]; i++) {
1808                         fstrcpy(temp_name, driver->dependentfiles[i]);
1809                         slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1810                 }
1811         }
1812
1813         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1814
1815         DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1816
1817         buf = NULL;
1818         len = buflen = 0;
1819
1820  again:
1821         len = 0;
1822         len += tdb_pack(buf+len, buflen-len, "dffffffff",
1823                         driver->cversion,
1824                         driver->name,
1825                         driver->environment,
1826                         driver->driverpath,
1827                         driver->datafile,
1828                         driver->configfile,
1829                         driver->helpfile,
1830                         driver->monitorname,
1831                         driver->defaultdatatype);
1832
1833         if (driver->dependentfiles) {
1834                 for (i=0; *driver->dependentfiles[i]; i++) {
1835                         len += tdb_pack(buf+len, buflen-len, "f",
1836                                         driver->dependentfiles[i]);
1837                 }
1838         }
1839
1840         if (len != buflen) {
1841                 char *tb;
1842
1843                 tb = (char *)SMB_REALLOC(buf, len);
1844                 if (!tb) {
1845                         DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1846                         ret = -1;
1847                         goto done;
1848                 }
1849                 else buf = tb;
1850                 buflen = len;
1851                 goto again;
1852         }
1853
1854
1855         kbuf.dptr = key;
1856         kbuf.dsize = strlen(key)+1;
1857         dbuf.dptr = buf;
1858         dbuf.dsize = len;
1859         
1860         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1861
1862 done:
1863         if (ret)
1864                 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1865
1866         SAFE_FREE(buf);
1867         return ret;
1868 }
1869
1870 /****************************************************************************
1871 ****************************************************************************/
1872 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1873 {
1874         NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1875
1876         ZERO_STRUCT(info3);
1877         info3.cversion = driver->version;
1878         fstrcpy(info3.name,driver->name);
1879         fstrcpy(info3.environment,driver->environment);
1880         fstrcpy(info3.driverpath,driver->driverpath);
1881         fstrcpy(info3.datafile,driver->datafile);
1882         fstrcpy(info3.configfile,driver->configfile);
1883         fstrcpy(info3.helpfile,driver->helpfile);
1884         fstrcpy(info3.monitorname,driver->monitorname);
1885         fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1886         info3.dependentfiles = driver->dependentfiles;
1887
1888         return add_a_printer_driver_3(&info3);
1889 }
1890
1891
1892 /****************************************************************************
1893 ****************************************************************************/
1894 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
1895 {
1896         NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1897
1898         ZERO_STRUCT(info);
1899
1900         fstrcpy(info.name, driver);
1901         fstrcpy(info.defaultdatatype, "RAW");
1902         
1903         fstrcpy(info.driverpath, "");
1904         fstrcpy(info.datafile, "");
1905         fstrcpy(info.configfile, "");
1906         fstrcpy(info.helpfile, "");
1907
1908         if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
1909                 return WERR_NOMEM;
1910
1911         memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1912         fstrcpy(info.dependentfiles[0], "");
1913
1914         *info_ptr = memdup(&info, sizeof(info));
1915         
1916         return WERR_OK;
1917 }
1918
1919 /****************************************************************************
1920 ****************************************************************************/
1921 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
1922 {
1923         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1924         TDB_DATA kbuf, dbuf;
1925         const char *architecture;
1926         int len = 0;
1927         int i;
1928         pstring key;
1929
1930         ZERO_STRUCT(driver);
1931
1932         architecture = get_short_archi(arch);
1933
1934         if ( !architecture )
1935                 return WERR_UNKNOWN_PRINTER_DRIVER;
1936         
1937         /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1938         
1939         if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
1940                 version = 0;
1941
1942         DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1943
1944         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1945
1946         kbuf.dptr = key;
1947         kbuf.dsize = strlen(key)+1;
1948         
1949         dbuf = tdb_fetch(tdb_drivers, kbuf);
1950         if (!dbuf.dptr) 
1951                 return WERR_UNKNOWN_PRINTER_DRIVER;
1952
1953         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1954                           &driver.cversion,
1955                           driver.name,
1956                           driver.environment,
1957                           driver.driverpath,
1958                           driver.datafile,
1959                           driver.configfile,
1960                           driver.helpfile,
1961                           driver.monitorname,
1962                           driver.defaultdatatype);
1963
1964         i=0;
1965         while (len < dbuf.dsize) {
1966                 fstring *tddfs;
1967
1968                 tddfs = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
1969                 if (tddfs == NULL) {
1970                         DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1971                         break;
1972                 }
1973                 else driver.dependentfiles = tddfs;
1974
1975                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1976                                   &driver.dependentfiles[i]);
1977                 i++;
1978         }
1979         
1980         if (driver.dependentfiles != NULL)
1981                 fstrcpy(driver.dependentfiles[i], "");
1982
1983         SAFE_FREE(dbuf.dptr);
1984
1985         if (len != dbuf.dsize) {
1986                 SAFE_FREE(driver.dependentfiles);
1987
1988                 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1989         }
1990
1991         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1992
1993         return WERR_OK;
1994 }
1995
1996 /****************************************************************************
1997  Debugging function, dump at level 6 the struct in the logs.
1998 ****************************************************************************/
1999
2000 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2001 {
2002         uint32 result;
2003         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2004         int i;
2005         
2006         DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2007         
2008         switch (level)
2009         {
2010                 case 3:
2011                 {
2012                         if (driver.info_3 == NULL)
2013                                 result=5;
2014                         else {
2015                                 info3=driver.info_3;
2016                         
2017                                 DEBUGADD(20,("version:[%d]\n",         info3->cversion));
2018                                 DEBUGADD(20,("name:[%s]\n",            info3->name));
2019                                 DEBUGADD(20,("environment:[%s]\n",     info3->environment));
2020                                 DEBUGADD(20,("driverpath:[%s]\n",      info3->driverpath));
2021                                 DEBUGADD(20,("datafile:[%s]\n",        info3->datafile));
2022                                 DEBUGADD(20,("configfile:[%s]\n",      info3->configfile));
2023                                 DEBUGADD(20,("helpfile:[%s]\n",        info3->helpfile));
2024                                 DEBUGADD(20,("monitorname:[%s]\n",     info3->monitorname));
2025                                 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2026                                 
2027                                 for (i=0; info3->dependentfiles &&
2028                                           *info3->dependentfiles[i]; i++) {
2029                                         DEBUGADD(20,("dependentfile:[%s]\n",
2030                                                       info3->dependentfiles[i]));
2031                                 }
2032                                 result=0;
2033                         }
2034                         break;
2035                 }
2036                 default:
2037                         DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2038                         result=1;
2039                         break;
2040         }
2041         
2042         return result;
2043 }
2044
2045 /****************************************************************************
2046 ****************************************************************************/
2047 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
2048 {
2049         int len = 0;
2050
2051         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2052
2053         if (!nt_devmode)
2054                 return len;
2055
2056         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2057                         nt_devmode->devicename,
2058                         nt_devmode->formname,
2059
2060                         nt_devmode->specversion,
2061                         nt_devmode->driverversion,
2062                         nt_devmode->size,
2063                         nt_devmode->driverextra,
2064                         nt_devmode->orientation,
2065                         nt_devmode->papersize,
2066                         nt_devmode->paperlength,
2067                         nt_devmode->paperwidth,
2068                         nt_devmode->scale,
2069                         nt_devmode->copies,
2070                         nt_devmode->defaultsource,
2071                         nt_devmode->printquality,
2072                         nt_devmode->color,
2073                         nt_devmode->duplex,
2074                         nt_devmode->yresolution,
2075                         nt_devmode->ttoption,
2076                         nt_devmode->collate,
2077                         nt_devmode->logpixels,
2078                         
2079                         nt_devmode->fields,
2080                         nt_devmode->bitsperpel,
2081                         nt_devmode->pelswidth,
2082                         nt_devmode->pelsheight,
2083                         nt_devmode->displayflags,
2084                         nt_devmode->displayfrequency,
2085                         nt_devmode->icmmethod,
2086                         nt_devmode->icmintent,
2087                         nt_devmode->mediatype,
2088                         nt_devmode->dithertype,
2089                         nt_devmode->reserved1,
2090                         nt_devmode->reserved2,
2091                         nt_devmode->panningwidth,
2092                         nt_devmode->panningheight,
2093                         nt_devmode->nt_dev_private);
2094
2095         
2096         if (nt_devmode->nt_dev_private) {
2097                 len += tdb_pack(buf+len, buflen-len, "B",
2098                                 nt_devmode->driverextra,
2099                                 nt_devmode->nt_dev_private);
2100         }
2101
2102         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2103
2104         return len;
2105 }
2106
2107 /****************************************************************************
2108  Pack all values in all printer keys
2109  ***************************************************************************/
2110  
2111 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
2112 {
2113         int             len = 0;
2114         int             i, j;
2115         REGISTRY_VALUE  *val;
2116         REGVAL_CTR      *val_ctr;
2117         pstring         path;
2118         int             num_values;
2119
2120         if ( !data )
2121                 return 0;
2122
2123         /* loop over all keys */
2124                 
2125         for ( i=0; i<data->num_keys; i++ ) {    
2126                 val_ctr = &data->keys[i].values;
2127                 num_values = regval_ctr_numvals( val_ctr );
2128
2129                 /* pack the keyname followed by a empty value */
2130
2131                 len += tdb_pack(buf+len, buflen-len, "pPdB", 
2132                                 &data->keys[i].name,
2133                                 data->keys[i].name, 
2134                                 REG_NONE,
2135                                 0,
2136                                 NULL);
2137                 
2138                 /* now loop over all values */
2139                 
2140                 for ( j=0; j<num_values; j++ ) {
2141                         /* pathname should be stored as <key>\<value> */
2142                         
2143                         val = regval_ctr_specific_value( val_ctr, j );
2144                         pstrcpy( path, data->keys[i].name );
2145                         pstrcat( path, "\\" );
2146                         pstrcat( path, regval_name(val) );
2147                         
2148                         len += tdb_pack(buf+len, buflen-len, "pPdB",
2149                                         val,
2150                                         path,
2151                                         regval_type(val),
2152                                         regval_size(val),
2153                                         regval_data_p(val) );
2154                 }
2155         
2156         }
2157
2158         /* terminator */
2159         
2160         len += tdb_pack(buf+len, buflen-len, "p", NULL);
2161
2162         return len;
2163 }
2164
2165
2166 /****************************************************************************
2167  Delete a printer - this just deletes the printer info file, any open
2168  handles are not affected.
2169 ****************************************************************************/
2170
2171 uint32 del_a_printer(const char *sharename)
2172 {
2173         pstring key;
2174         TDB_DATA kbuf;
2175         pstring printdb_path;
2176
2177         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2178         kbuf.dptr=key;
2179         kbuf.dsize=strlen(key)+1;
2180         tdb_delete(tdb_printers, kbuf);
2181
2182         slprintf(key, sizeof(key)-1, "%s%s", SECDESC_PREFIX, sharename);
2183         kbuf.dptr=key;
2184         kbuf.dsize=strlen(key)+1;
2185         tdb_delete(tdb_printers, kbuf);
2186
2187         close_all_print_db();
2188
2189         if (geteuid() == 0) {
2190                 pstrcpy(printdb_path, lock_path("printing/"));
2191                 pstrcat(printdb_path, sharename);
2192                 pstrcat(printdb_path, ".tdb");
2193
2194                 unlink(printdb_path);
2195         }
2196
2197         return 0;
2198 }
2199
2200 /****************************************************************************
2201 ****************************************************************************/
2202 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2203 {
2204         pstring key;
2205         fstring norm_sharename;
2206         char *buf;
2207         int buflen, len;
2208         WERROR ret;
2209         TDB_DATA kbuf, dbuf;
2210         
2211         /*
2212          * in addprinter: no servername and the printer is the name
2213          * in setprinter: servername is \\server
2214          *                and printer is \\server\\printer
2215          *
2216          * Samba manages only local printers.
2217          * we currently don't support things like i
2218          * path=\\other_server\printer
2219          *
2220          * We only store the printername, not \\server\printername
2221          */
2222
2223         if ( info->servername[0] != '\0' ) {
2224                 trim_string(info->printername, info->servername, NULL);
2225                 trim_char(info->printername, '\\', '\0');
2226                 info->servername[0]='\0';
2227         }
2228
2229         /*
2230          * JFM: one day I'll forget.
2231          * below that's info->portname because that's the SAMBA sharename
2232          * and I made NT 'thinks' it's the portname
2233          * the info->sharename is the thing you can name when you add a printer
2234          * that's the short-name when you create shared printer for 95/98
2235          * So I've made a limitation in SAMBA: you can only have 1 printer model
2236          * behind a SAMBA share.
2237          */
2238
2239         buf = NULL;
2240         buflen = 0;
2241
2242  again: 
2243         len = 0;
2244         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2245                         info->attributes,
2246                         info->priority,
2247                         info->default_priority,
2248                         info->starttime,
2249                         info->untiltime,
2250                         info->status,
2251                         info->cjobs,
2252                         info->averageppm,
2253                         info->changeid,
2254                         info->c_setprinter,
2255                         info->setuptime,
2256                         info->servername,
2257                         info->printername,
2258                         info->sharename,
2259                         info->portname,
2260                         info->drivername,
2261                         info->comment,
2262                         info->location,
2263                         info->sepfile,
2264                         info->printprocessor,
2265                         info->datatype,
2266                         info->parameters);
2267
2268         len += pack_devicemode(info->devmode, buf+len, buflen-len);
2269         
2270         len += pack_values( &info->data, buf+len, buflen-len );
2271
2272         if (buflen != len) {
2273                 char *tb;
2274
2275                 tb = (char *)SMB_REALLOC(buf, len);
2276                 if (!tb) {
2277                         DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2278                         ret = WERR_NOMEM;
2279                         goto done;
2280                 }
2281                 else buf = tb;
2282                 buflen = len;
2283                 goto again;
2284         }
2285         
2286
2287         /* normalize the key */
2288
2289         fstrcpy( norm_sharename, info->sharename );
2290         strlower_m( norm_sharename );
2291
2292         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2293
2294         kbuf.dptr = key;
2295         kbuf.dsize = strlen(key)+1;
2296         dbuf.dptr = buf;
2297         dbuf.dsize = len;
2298
2299         ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2300
2301 done:
2302         if (!W_ERROR_IS_OK(ret))
2303                 DEBUG(8, ("error updating printer to tdb on disk\n"));
2304
2305         SAFE_FREE(buf);
2306
2307         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2308                  info->sharename, info->drivername, info->portname, len));
2309
2310         return ret;
2311 }
2312
2313
2314 /****************************************************************************
2315  Malloc and return an NT devicemode.
2316 ****************************************************************************/
2317
2318 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2319 {
2320
2321         char adevice[MAXDEVICENAME];
2322         NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2323
2324         if (nt_devmode == NULL) {
2325                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2326                 return NULL;
2327         }
2328
2329         ZERO_STRUCTP(nt_devmode);
2330
2331         slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2332         fstrcpy(nt_devmode->devicename, adevice);       
2333         
2334         fstrcpy(nt_devmode->formname, "Letter");
2335
2336         nt_devmode->specversion      = 0x0401;
2337         nt_devmode->driverversion    = 0x0400;
2338         nt_devmode->size             = 0x00DC;
2339         nt_devmode->driverextra      = 0x0000;
2340         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY |
2341                                        DEFAULTSOURCE | COPIES | SCALE |
2342                                        PAPERSIZE | ORIENTATION;
2343         nt_devmode->orientation      = 1;
2344         nt_devmode->papersize        = PAPER_LETTER;
2345         nt_devmode->paperlength      = 0;
2346         nt_devmode->paperwidth       = 0;
2347         nt_devmode->scale            = 0x64;
2348         nt_devmode->copies           = 1;
2349         nt_devmode->defaultsource    = BIN_FORMSOURCE;
2350         nt_devmode->printquality     = RES_HIGH;           /* 0x0258 */
2351         nt_devmode->color            = COLOR_MONOCHROME;
2352         nt_devmode->duplex           = DUP_SIMPLEX;
2353         nt_devmode->yresolution      = 0;
2354         nt_devmode->ttoption         = TT_SUBDEV;
2355         nt_devmode->collate          = COLLATE_FALSE;
2356         nt_devmode->icmmethod        = 0;
2357         nt_devmode->icmintent        = 0;
2358         nt_devmode->mediatype        = 0;
2359         nt_devmode->dithertype       = 0;
2360
2361         /* non utilisés par un driver d'imprimante */
2362         nt_devmode->logpixels        = 0;
2363         nt_devmode->bitsperpel       = 0;
2364         nt_devmode->pelswidth        = 0;
2365         nt_devmode->pelsheight       = 0;
2366         nt_devmode->displayflags     = 0;
2367         nt_devmode->displayfrequency = 0;
2368         nt_devmode->reserved1        = 0;
2369         nt_devmode->reserved2        = 0;
2370         nt_devmode->panningwidth     = 0;
2371         nt_devmode->panningheight    = 0;
2372         
2373         nt_devmode->nt_dev_private = NULL;
2374         return nt_devmode;
2375 }
2376
2377 /****************************************************************************
2378  Deepcopy an NT devicemode.
2379 ****************************************************************************/
2380
2381 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2382 {
2383         NT_DEVICEMODE *new_nt_devicemode = NULL;
2384
2385         if ( !nt_devicemode )
2386                 return NULL;
2387
2388         if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2389                 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2390                 return NULL;
2391         }
2392
2393         new_nt_devicemode->nt_dev_private = NULL;
2394         if (nt_devicemode->nt_dev_private != NULL) {
2395                 if ((new_nt_devicemode->nt_dev_private = memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2396                         SAFE_FREE(new_nt_devicemode);
2397                         DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2398                         return NULL;
2399         }
2400         }
2401
2402         return new_nt_devicemode;
2403 }
2404
2405 /****************************************************************************
2406  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2407 ****************************************************************************/
2408
2409 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2410 {
2411         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2412
2413         if(nt_devmode == NULL)
2414                 return;
2415
2416         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2417
2418         SAFE_FREE(nt_devmode->nt_dev_private);
2419         SAFE_FREE(*devmode_ptr);
2420 }
2421
2422 /****************************************************************************
2423  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2424 ****************************************************************************/
2425 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2426 {
2427         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2428         NT_PRINTER_DATA         *data;
2429         int                     i;
2430
2431         if ( !info )
2432                 return;
2433
2434         DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2435
2436         free_nt_devicemode(&info->devmode);
2437
2438         /* clean up all registry keys */
2439         
2440         data = &info->data;
2441         for ( i=0; i<data->num_keys; i++ ) {
2442                 SAFE_FREE( data->keys[i].name );
2443                 regval_ctr_destroy( &data->keys[i].values );
2444         }
2445         SAFE_FREE( data->keys );
2446
2447         /* finally the top level structure */
2448         
2449         SAFE_FREE( *info_ptr );
2450 }
2451
2452
2453 /****************************************************************************
2454 ****************************************************************************/
2455 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2456 {
2457         int len = 0;
2458         int extra_len = 0;
2459         NT_DEVICEMODE devmode;
2460         
2461         ZERO_STRUCT(devmode);
2462
2463         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2464
2465         if (!*nt_devmode) return len;
2466
2467         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2468                           devmode.devicename,
2469                           devmode.formname,
2470
2471                           &devmode.specversion,
2472                           &devmode.driverversion,
2473                           &devmode.size,
2474                           &devmode.driverextra,
2475                           &devmode.orientation,
2476                           &devmode.papersize,
2477                           &devmode.paperlength,
2478                           &devmode.paperwidth,
2479                           &devmode.scale,
2480                           &devmode.copies,
2481                           &devmode.defaultsource,
2482                           &devmode.printquality,
2483                           &devmode.color,
2484                           &devmode.duplex,
2485                           &devmode.yresolution,
2486                           &devmode.ttoption,
2487                           &devmode.collate,
2488                           &devmode.logpixels,
2489                         
2490                           &devmode.fields,
2491                           &devmode.bitsperpel,
2492                           &devmode.pelswidth,
2493                           &devmode.pelsheight,
2494                           &devmode.displayflags,
2495                           &devmode.displayfrequency,
2496                           &devmode.icmmethod,
2497                           &devmode.icmintent,
2498                           &devmode.mediatype,
2499                           &devmode.dithertype,
2500                           &devmode.reserved1,
2501                           &devmode.reserved2,
2502                           &devmode.panningwidth,
2503                           &devmode.panningheight,
2504                           &devmode.nt_dev_private);
2505         
2506         if (devmode.nt_dev_private) {
2507                 /* the len in tdb_unpack is an int value and
2508                  * devmode.driverextra is only a short
2509                  */
2510                 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2511                 devmode.driverextra=(uint16)extra_len;
2512                 
2513                 /* check to catch an invalid TDB entry so we don't segfault */
2514                 if (devmode.driverextra == 0) {
2515                         devmode.nt_dev_private = NULL;
2516                 }
2517         }
2518
2519         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2520
2521         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2522         if (devmode.nt_dev_private)
2523                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2524
2525         return len;
2526 }
2527
2528 /****************************************************************************
2529  Allocate and initialize a new slot.
2530 ***************************************************************************/
2531  
2532 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2533 {
2534         NT_PRINTER_KEY  *d;
2535         int             key_index;
2536         
2537         if ( !data || !name )
2538                 return -1;
2539         
2540         /* allocate another slot in the NT_PRINTER_KEY array */
2541         
2542         if ( !(d = SMB_REALLOC_ARRAY( data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2543                 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2544                 return -1;
2545         }
2546
2547         data->keys = d;
2548         
2549         key_index = data->num_keys;
2550         
2551         /* initialze new key */
2552         
2553         data->num_keys++;
2554         data->keys[key_index].name = SMB_STRDUP( name );
2555         
2556         regval_ctr_init( &data->keys[key_index].values );
2557         
2558         DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2559         
2560         return key_index;
2561 }
2562
2563 /****************************************************************************
2564  search for a registry key name in the existing printer data
2565  ***************************************************************************/
2566  
2567 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2568 {
2569         int             key_index = -1;
2570         int             i;
2571         
2572         if ( !data || !name )
2573                 return -1;
2574
2575         DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2576
2577         /* loop over all existing keys */
2578         
2579         for ( i=0; i<data->num_keys; i++ ) {
2580                 if ( strequal(data->keys[i].name, name) ) {
2581                         DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2582                         key_index = i;
2583                         break;
2584                 
2585                 }
2586         }
2587         
2588         return key_index;
2589 }
2590
2591 /****************************************************************************
2592  ***************************************************************************/
2593
2594 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2595 {
2596         int     i, j;
2597         int     key_len;
2598         int     num_subkeys = 0;
2599         char    *p;
2600         fstring *ptr, *subkeys_ptr = NULL;
2601         fstring subkeyname;
2602         
2603         if ( !data )
2604                 return 0;
2605
2606         if ( !key )
2607                 return -1;
2608
2609         /* special case of asking for the top level printer data registry key names */
2610
2611         if ( strlen(key) == 0 ) {
2612                 for ( i=0; i<data->num_keys; i++ ) {
2613                 
2614                         /* found a match, so allocate space and copy the name */
2615                         
2616                         if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2617                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 
2618                                         num_subkeys+1));
2619                                 SAFE_FREE( subkeys );
2620                                 return -1;
2621                         }
2622                         
2623                         subkeys_ptr = ptr;
2624                         fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2625                         num_subkeys++;
2626                 }
2627
2628                 goto done;
2629         }
2630                 
2631         /* asking for the subkeys of some key */
2632         /* subkey paths are stored in the key name using '\' as the delimiter */
2633
2634         for ( i=0; i<data->num_keys; i++ ) {
2635                 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2636                         
2637                         /* if we found the exact key, then break */
2638                         key_len = strlen( key );
2639                         if ( strlen(data->keys[i].name) == key_len )
2640                                 break;
2641                         
2642                         /* get subkey path */
2643
2644                         p = data->keys[i].name + key_len;
2645                         if ( *p == '\\' )
2646                                 p++;
2647                         fstrcpy( subkeyname, p );
2648                         if ( (p = strchr( subkeyname, '\\' )) )
2649                                 *p = '\0';
2650                         
2651                         /* don't add a key more than once */
2652                         
2653                         for ( j=0; j<num_subkeys; j++ ) {
2654                                 if ( strequal( subkeys_ptr[j], subkeyname ) )
2655                                         break;
2656                         }
2657                         
2658                         if ( j != num_subkeys )
2659                                 continue;
2660
2661                         /* found a match, so allocate space and copy the name */
2662                         
2663                         if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2664                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 
2665                                         num_subkeys+1));
2666                                 SAFE_FREE( subkeys );
2667                                 return 0;
2668                         }
2669                         
2670                         subkeys_ptr = ptr;
2671                         fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2672                         num_subkeys++;
2673                 }
2674                 
2675         }
2676         
2677         /* return error if the key was not found */
2678         
2679         if ( i == data->num_keys )
2680                 return -1;
2681         
2682 done:
2683         /* tag off the end */
2684         
2685         if (num_subkeys)
2686                 fstrcpy(subkeys_ptr[num_subkeys], "" );
2687         
2688         *subkeys = subkeys_ptr;
2689
2690         return num_subkeys;
2691 }
2692
2693 #ifdef HAVE_ADS
2694 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name, 
2695                             const char *sz)
2696 {
2697         smb_ucs2_t conv_str[1024];
2698         size_t str_size;
2699
2700         regval_ctr_delvalue(ctr, val_name);
2701         str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2702                              STR_TERMINATE | STR_NOALIGN);
2703         regval_ctr_addvalue(ctr, val_name, REG_SZ, 
2704                             (char *) conv_str, str_size);
2705 }
2706
2707 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name, 
2708                                uint32 dword)
2709 {
2710         regval_ctr_delvalue(ctr, val_name);
2711         regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2712                             (char *) &dword, sizeof(dword));
2713 }
2714
2715 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2716                               BOOL b)
2717 {
2718         uint8 bin_bool = (b ? 1 : 0);
2719         regval_ctr_delvalue(ctr, val_name);
2720         regval_ctr_addvalue(ctr, val_name, REG_BINARY, 
2721                             (char *) &bin_bool, sizeof(bin_bool));
2722 }
2723
2724 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2725                                          const char *multi_sz)
2726 {
2727         smb_ucs2_t *conv_strs = NULL;
2728         size_t str_size;
2729
2730         /* a multi-sz has to have a null string terminator, i.e., the last
2731            string must be followed by two nulls */
2732         str_size = strlen(multi_sz) + 2;
2733         conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2734         if (!conv_strs) {
2735                 return;
2736         }
2737
2738         /* Change to byte units. */
2739         str_size *= sizeof(smb_ucs2_t);
2740         push_ucs2(NULL, conv_strs, multi_sz, str_size, 
2741                   STR_TERMINATE | STR_NOALIGN);
2742
2743         regval_ctr_delvalue(ctr, val_name);
2744         regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ, 
2745                             (char *) conv_strs, str_size);      
2746         safe_free(conv_strs);
2747         
2748 }
2749
2750 /****************************************************************************
2751  * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2752  *
2753  * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2754  * @return BOOL indicating success or failure
2755  ***************************************************************************/
2756
2757 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2758 {
2759         REGVAL_CTR *ctr = NULL;
2760         fstring longname;
2761         fstring dnssuffix;
2762         char *allocated_string = NULL;
2763         const char *ascii_str;
2764         int i;
2765
2766         if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2767                 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2768         ctr = &info2->data.keys[i].values;
2769
2770         map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2771         map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2772
2773         /* we make the assumption that the netbios name is the same 
2774            as the DNS name sinc ethe former will be what we used to 
2775            join the domain */
2776
2777         if ( get_mydnsdomname( dnssuffix ) )
2778                 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2779         else
2780                 fstrcpy( longname, global_myname() );
2781                 
2782         map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2783
2784         asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2785         map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2786         SAFE_FREE(allocated_string);
2787
2788         map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2789         map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2790         map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2791         map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2792         map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2793         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2794         map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2795         map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2796         map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2797
2798         map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2799                           (info2->attributes & 
2800                            PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2801
2802         switch (info2->attributes & 0x3) {
2803         case 0:
2804                 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2805                 break;
2806         case 1:
2807                 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2808                 break;
2809         case 2:
2810                 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2811                 break;
2812         default:
2813                 ascii_str = "unknown";
2814         }
2815         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2816
2817         return True;
2818 }
2819
2820 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2, 
2821                                struct uuid guid)
2822 {
2823         int i;
2824         REGVAL_CTR *ctr=NULL;
2825
2826         /* find the DsSpooler key */
2827         if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2828                 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2829         ctr = &info2->data.keys[i].values;
2830
2831         regval_ctr_delvalue(ctr, "objectGUID");
2832         regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY, 
2833                             (char *) &guid, sizeof(struct uuid));       
2834 }
2835
2836 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2837                                      NT_PRINTER_INFO_LEVEL *printer)
2838 {
2839         ADS_STATUS ads_rc;
2840         void *res;
2841         char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2842         char *srv_dn_utf8, **srv_cn_utf8;
2843         TALLOC_CTX *ctx;
2844         ADS_MODLIST mods;
2845         const char *attrs[] = {"objectGUID", NULL};
2846         struct uuid guid;
2847         WERROR win_rc = WERR_OK;
2848
2849         DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
2850
2851         /* figure out where to publish */
2852         ads_find_machine_acct(ads, &res, global_myname());
2853
2854         /* We use ldap_get_dn here as we need the answer
2855          * in utf8 to call ldap_explode_dn(). JRA. */
2856
2857         srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2858         if (!srv_dn_utf8) {
2859                 ads_destroy(&ads);
2860                 return WERR_SERVER_UNAVAILABLE;
2861         }
2862         ads_msgfree(ads, res);
2863         srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2864         if (!srv_cn_utf8) {
2865                 ldap_memfree(srv_dn_utf8);
2866                 ads_destroy(&ads);
2867                 return WERR_SERVER_UNAVAILABLE;
2868         }
2869         /* Now convert to CH_UNIX. */
2870         if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
2871                 ldap_memfree(srv_dn_utf8);
2872                 ldap_memfree(srv_cn_utf8);
2873                 ads_destroy(&ads);
2874                 return WERR_SERVER_UNAVAILABLE;
2875         }
2876         if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
2877                 ldap_memfree(srv_dn_utf8);
2878                 ldap_memfree(srv_cn_utf8);
2879                 ads_destroy(&ads);
2880                 SAFE_FREE(srv_dn);
2881                 return WERR_SERVER_UNAVAILABLE;
2882         }
2883
2884         ldap_memfree(srv_dn_utf8);
2885         ldap_memfree(srv_cn_utf8);
2886
2887         asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0, 
2888                  printer->info_2->sharename, srv_dn);
2889
2890         SAFE_FREE(srv_dn);
2891         SAFE_FREE(srv_cn_0);
2892
2893         /* build the ads mods */
2894         ctx = talloc_init("nt_printer_publish_ads");
2895         mods = ads_init_mods(ctx);
2896
2897         get_local_printer_publishing_data(ctx, &mods, 
2898                                           &printer->info_2->data);
2899         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, 
2900                     printer->info_2->sharename);
2901
2902         /* publish it */
2903         ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
2904         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
2905                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2906
2907         if (!ADS_ERR_OK(ads_rc))
2908                 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
2909         
2910         talloc_destroy(ctx);
2911
2912         /* retreive the guid and store it locally */
2913         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2914                 ZERO_STRUCT(guid);
2915                 ads_pull_guid(ads, res, &guid);
2916                 ads_msgfree(ads, res);
2917                 store_printer_guid(printer->info_2, guid);
2918                 win_rc = mod_a_printer(printer, 2);
2919         } 
2920
2921         SAFE_FREE(prt_dn);
2922         return win_rc;
2923 }
2924
2925 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
2926                                        NT_PRINTER_INFO_LEVEL *printer)
2927 {
2928         ADS_STATUS ads_rc;
2929         void *res;
2930         char *prt_dn = NULL;
2931
2932         DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
2933
2934         /* remove the printer from the directory */
2935         ads_rc = ads_find_printer_on_server(ads, &res, 
2936                             printer->info_2->sharename, global_myname());
2937
2938         if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2939                 prt_dn = ads_get_dn(ads, res);
2940                 ads_rc = ads_del_dn(ads, prt_dn);
2941                 ads_memfree(ads, prt_dn);
2942         }
2943
2944         ads_msgfree(ads, res);
2945         return WERR_OK;
2946 }
2947
2948 /****************************************************************************
2949  * Publish a printer in the directory
2950  *
2951  * @param snum describing printer service
2952  * @return WERROR indicating status of publishing
2953  ***************************************************************************/
2954
2955 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2956 {
2957         ADS_STATUS ads_rc;
2958         ADS_STRUCT *ads = NULL;
2959         NT_PRINTER_INFO_LEVEL *printer = NULL;
2960         WERROR win_rc;
2961
2962         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2963         if (!W_ERROR_IS_OK(win_rc))
2964                 goto done;
2965
2966         switch (action) {
2967         case SPOOL_DS_PUBLISH:
2968         case SPOOL_DS_UPDATE:
2969                 /* set the DsSpooler info and attributes */
2970                 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
2971                         win_rc = WERR_NOMEM;
2972                         goto done;
2973                 }
2974
2975                 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2976                 break;
2977         case SPOOL_DS_UNPUBLISH:
2978                 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2979                 break;
2980         default:
2981                 win_rc = WERR_NOT_SUPPORTED;
2982                 goto done;
2983         }
2984
2985         win_rc = mod_a_printer(printer, 2);
2986         if (!W_ERROR_IS_OK(win_rc)) {
2987                 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
2988                 goto done;
2989         }
2990
2991         ads = ads_init(NULL, NULL, NULL);
2992         if (!ads) {
2993                 DEBUG(3, ("ads_init() failed\n"));
2994                 win_rc = WERR_SERVER_UNAVAILABLE;
2995                 goto done;
2996         }
2997         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2998         SAFE_FREE(ads->auth.password);
2999         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3000                 NULL, NULL);
3001
3002         /* ads_connect() will find the DC for us */                                         
3003         ads_rc = ads_connect(ads);
3004         if (!ADS_ERR_OK(ads_rc)) {
3005                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3006                 win_rc = WERR_ACCESS_DENIED;
3007                 goto done;
3008         }
3009
3010         switch (action) {
3011         case SPOOL_DS_PUBLISH:
3012         case SPOOL_DS_UPDATE:
3013                 win_rc = nt_printer_publish_ads(ads, printer);
3014                 break;
3015         case SPOOL_DS_UNPUBLISH:
3016                 win_rc = nt_printer_unpublish_ads(ads, printer);
3017                 break;
3018         }
3019
3020 done:
3021         free_a_printer(&printer, 2);
3022         ads_destroy(&ads);
3023         return win_rc;
3024 }
3025
3026 WERROR check_published_printers(void)
3027 {
3028         ADS_STATUS ads_rc;
3029         ADS_STRUCT *ads = NULL;
3030         int snum;
3031         int n_services = lp_numservices();
3032         NT_PRINTER_INFO_LEVEL *printer = NULL;
3033
3034         ads = ads_init(NULL, NULL, NULL);
3035         if (!ads) {
3036                 DEBUG(3, ("ads_init() failed\n"));
3037                 return WERR_SERVER_UNAVAILABLE;
3038         }
3039         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3040         SAFE_FREE(ads->auth.password);
3041         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3042                 NULL, NULL);
3043
3044         /* ads_connect() will find the DC for us */                                         
3045         ads_rc = ads_connect(ads);
3046         if (!ADS_ERR_OK(ads_rc)) {
3047                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3048                 ads_destroy(&ads);
3049                 return WERR_ACCESS_DENIED;
3050         }
3051
3052         for (snum = 0; snum < n_services; snum++) {
3053                 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3054                         continue;
3055
3056                 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3057                                                 lp_servicename(snum))) &&
3058                     (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3059                         nt_printer_publish_ads(ads, printer);
3060
3061                 free_a_printer(&printer, 2);
3062         }
3063
3064         ads_destroy(&ads);
3065         return WERR_OK;
3066 }
3067
3068 BOOL is_printer_published(Printer_entry *print_hnd, int snum, 
3069                           struct uuid *guid)
3070 {
3071         NT_PRINTER_INFO_LEVEL *printer = NULL;
3072         REGVAL_CTR *ctr;
3073         REGISTRY_VALUE *guid_val;
3074         WERROR win_rc;
3075         int i;
3076
3077         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3078
3079         if (!W_ERROR_IS_OK(win_rc) ||
3080             !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3081             ((i = lookup_printerkey(&printer->info_2->data, 
3082          &nb