r8089: successfully delete printer subkeys via the registry....now for values
[nivanova/samba-autobuild/.git] / source3 / printing / nt_printing.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2000.
6  *  Copyright (C) Gerald Carter                2002-2003.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include "includes.h"
24
25 extern struct current_user current_user;
26
27 static TDB_CONTEXT *tdb_forms; /* used for forms files */
28 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29 static TDB_CONTEXT *tdb_printers; /* used for printers files */
30
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
37  
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
41 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
42  
43 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_4
44
45 /* Map generic permissions to printer object specific permissions */
46
47 GENERIC_MAPPING printer_generic_mapping = {
48         PRINTER_READ,
49         PRINTER_WRITE,
50         PRINTER_EXECUTE,
51         PRINTER_ALL_ACCESS
52 };
53
54 STANDARD_MAPPING printer_std_mapping = {
55         PRINTER_READ,
56         PRINTER_WRITE,
57         PRINTER_EXECUTE,
58         PRINTER_ALL_ACCESS
59 };
60
61 /* Map generic permissions to print server object specific permissions */
62
63 GENERIC_MAPPING printserver_generic_mapping = {
64         SERVER_READ,
65         SERVER_WRITE,
66         SERVER_EXECUTE,
67         SERVER_ALL_ACCESS
68 };
69
70 STANDARD_MAPPING printserver_std_mapping = {
71         SERVER_READ,
72         SERVER_WRITE,
73         SERVER_EXECUTE,
74         SERVER_ALL_ACCESS
75 };
76
77 /* We need one default form to support our default printer. Msoft adds the
78 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
79 array index). Letter is always first, so (for the current code) additions
80 always put things in the correct order. */
81 static const nt_forms_struct default_forms[] = {
82         {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83         {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
84         {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
85         {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
86         {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
87         {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
88         {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
89         {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
90         {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91         {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
92         {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
93         {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
94         {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
95         {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
96         {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
97         {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
98         {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
99         {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
100         {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
101         {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
102         {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
103         {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
104         {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
105         {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
106         {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
107         {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
108         {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
109         {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
110         {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
111         {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
112         {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
113         {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
114         {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
115         {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
116         {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
117         {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
118         {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
119         {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
120         {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
121         {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
122         {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
123         {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
124         {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
125         {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
126         {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
127         {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
128         {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
129         {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130         {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
131         {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
132         {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
133         {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
134         {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
135         {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
136         {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
137         {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
138         {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
139         {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
140         {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
141         {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
142         {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
143         {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
144         {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
145         {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
146         {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
147         {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
148         {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
149         {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
150         {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
151         {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
152         {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
153         {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
154         {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
155         {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
156         {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
157         {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
158         {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
159         {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
160         {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
161         {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
162         {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
163         {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
164         {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
165         {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
166         {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
167         {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
168         {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
169         {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
170         {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
171         {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
172         {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
173         {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
174         {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
175         {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
176         {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
177         {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
178         {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
179         {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
180         {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
181         {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
182         {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
183         {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
184         {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
185         {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
186         {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
187         {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
188         {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
189         {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
190         {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
191         {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
192         {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
193         {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
194         {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
195         {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
196         {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
197         {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
198         {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
199         {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
200 };
201
202 struct table_node {
203         const char      *long_archi;
204         const char      *short_archi;
205         int     version;
206 };
207  
208 #define SPL_ARCH_WIN40          "WIN40"
209 #define SPL_ARCH_W32X86         "W32X86"
210 #define SPL_ARCH_W32MIPS        "W32MIPS"
211 #define SPL_ARCH_W32ALPHA       "W32ALPHA"
212 #define SPL_ARCH_W32PPC         "W32PPC"
213 #define SPL_ARCH_IA64           "IA64"
214 #define SPL_ARCH_X64            "x64"
215
216 static const struct table_node archi_table[]= {
217
218         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
219         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
220         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
221         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
222         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
223         {"Windows IA64",         SPL_ARCH_IA64,         3 },
224         {"Windows x64",          SPL_ARCH_X64,          3 },
225         {NULL,                   "",            -1 }
226 };
227
228 static BOOL upgrade_to_version_3(void)
229 {
230         TDB_DATA kbuf, newkey, dbuf;
231  
232         DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
233  
234         for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
235                         newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
236
237                 dbuf = tdb_fetch(tdb_drivers, kbuf);
238
239                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
240                         DEBUG(0,("upgrade_to_version_3:moving form\n"));
241                         if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
242                                 SAFE_FREE(dbuf.dptr);
243                                 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
244                                 return False;
245                         }
246                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
247                                 SAFE_FREE(dbuf.dptr);
248                                 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
249                                 return False;
250                         }
251                 }
252  
253                 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
254                         DEBUG(0,("upgrade_to_version_3:moving printer\n"));
255                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
256                                 SAFE_FREE(dbuf.dptr);
257                                 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
258                                 return False;
259                         }
260                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
261                                 SAFE_FREE(dbuf.dptr);
262                                 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
263                                 return False;
264                         }
265                 }
266  
267                 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
268                         DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
269                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
270                                 SAFE_FREE(dbuf.dptr);
271                                 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
272                                 return False;
273                         }
274                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
275                                 SAFE_FREE(dbuf.dptr);
276                                 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
277                                 return False;
278                         }
279                 }
280  
281                 SAFE_FREE(dbuf.dptr);
282         }
283
284         return True;
285 }
286
287 /*******************************************************************
288  Fix an issue with security descriptors.  Printer sec_desc must 
289  use more than the generic bits that were previously used 
290  in <= 3.0.14a.  They must also have a owner and group SID assigned.
291  Otherwise, any printers than have been migrated to a Windows 
292  host using printmig.exe will not be accessible.
293 *******************************************************************/
294
295 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
296                             TDB_DATA data, void *state )
297 {
298         prs_struct ps;
299         SEC_DESC_BUF *sd_orig = NULL;
300         SEC_DESC_BUF *sd_new, *sd_store;
301         SEC_DESC *sec, *new_sec;
302         TALLOC_CTX *ctx = state;
303         int result, i;
304         uint32 sd_size, size_new_sec;
305         DOM_SID sid;
306
307         if (!data.dptr || data.dsize == 0)
308                 return 0;
309
310         if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 )
311                 return 0;
312
313         /* upgrade the security descriptor */
314
315         ZERO_STRUCT( ps );
316
317         prs_init( &ps, 0, ctx, UNMARSHALL );
318         prs_give_memory( &ps, data.dptr, data.dsize, True );
319
320         if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
321                 /* delete bad entries */
322                 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si.  Deleting....\n", key.dptr ));
323                 tdb_delete( tdb_printers, key );
324                 return 0;
325         }
326
327         sec = sd_orig->sec;
328                 
329         /* is this even valid? */
330         
331         if ( !sec->dacl )
332                 return 0;
333                 
334         /* update access masks */
335         
336         for ( i=0; i<sec->dacl->num_aces; i++ ) {
337                 switch ( sec->dacl->ace[i].info.mask ) {
338                         case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
339                                 sec->dacl->ace[i].info.mask = PRINTER_ACE_PRINT;
340                                 break;
341                                 
342                         case GENERIC_ALL_ACCESS:
343                                 sec->dacl->ace[i].info.mask = PRINTER_ACE_FULL_CONTROL;
344                                 break;
345                                 
346                         case READ_CONTROL_ACCESS:
347                                 sec->dacl->ace[i].info.mask = PRINTER_ACE_MANAGE_DOCUMENTS;
348                         
349                         default:        /* no change */
350                                 break;
351                 }
352         }
353
354         /* create a new SEC_DESC with the appropriate owner and group SIDs */
355
356         string_to_sid(&sid, "S-1-5-32-544" );
357         new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, 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 delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2568 {
2569         int i;
2570         NT_PRINTER_KEY *printer_key;
2571         
2572         for ( i=0; i<data->num_keys; i++ ) {
2573                 if ( strequal( data->keys[i].name, name ) ) {
2574                 
2575                         /* cleanup memory */
2576                         
2577                         printer_key = &data->keys[i];
2578                         SAFE_FREE( printer_key->name );
2579                         regval_ctr_destroy( &printer_key->values );
2580                         
2581                         /* if not the end of the array, move remaining elements down one slot */
2582                         
2583                         data->num_keys--;
2584                         if ( data->num_keys && (i < data->num_keys) )
2585                                 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2586                                 
2587                         break;
2588                 }
2589         }
2590         
2591
2592         return data->num_keys;
2593 }
2594
2595 /****************************************************************************
2596  search for a registry key name in the existing printer data
2597  ***************************************************************************/
2598  
2599 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2600 {
2601         int             key_index = -1;
2602         int             i;
2603         
2604         if ( !data || !name )
2605                 return -1;
2606
2607         DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2608
2609         /* loop over all existing keys */
2610         
2611         for ( i=0; i<data->num_keys; i++ ) {
2612                 if ( strequal(data->keys[i].name, name) ) {
2613                         DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2614                         key_index = i;
2615                         break;
2616                 
2617                 }
2618         }
2619         
2620         return key_index;
2621 }
2622
2623 /****************************************************************************
2624  ***************************************************************************/
2625
2626 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2627 {
2628         int     i, j;
2629         int     key_len;
2630         int     num_subkeys = 0;
2631         char    *p;
2632         fstring *ptr, *subkeys_ptr = NULL;
2633         fstring subkeyname;
2634         
2635         if ( !data )
2636                 return 0;
2637
2638         if ( !key )
2639                 return -1;
2640
2641         /* special case of asking for the top level printer data registry key names */
2642
2643         if ( strlen(key) == 0 ) {
2644                 for ( i=0; i<data->num_keys; i++ ) {
2645                 
2646                         /* found a match, so allocate space and copy the name */
2647                         
2648                         if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2649                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 
2650                                         num_subkeys+1));
2651                                 SAFE_FREE( subkeys );
2652                                 return -1;
2653                         }
2654                         
2655                         subkeys_ptr = ptr;
2656                         fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2657                         num_subkeys++;
2658                 }
2659
2660                 goto done;
2661         }
2662                 
2663         /* asking for the subkeys of some key */
2664         /* subkey paths are stored in the key name using '\' as the delimiter */
2665
2666         for ( i=0; i<data->num_keys; i++ ) {
2667                 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2668                         
2669                         /* if we found the exact key, then break */
2670                         key_len = strlen( key );
2671                         if ( strlen(data->keys[i].name) == key_len )
2672                                 break;
2673                         
2674                         /* get subkey path */
2675
2676                         p = data->keys[i].name + key_len;
2677                         if ( *p == '\\' )
2678                                 p++;
2679                         fstrcpy( subkeyname, p );
2680                         if ( (p = strchr( subkeyname, '\\' )) )
2681                                 *p = '\0';
2682                         
2683                         /* don't add a key more than once */
2684                         
2685                         for ( j=0; j<num_subkeys; j++ ) {
2686                                 if ( strequal( subkeys_ptr[j], subkeyname ) )
2687                                         break;
2688                         }
2689                         
2690                         if ( j != num_subkeys )
2691                                 continue;
2692
2693                         /* found a match, so allocate space and copy the name */
2694                         
2695                         if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2696                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 
2697                                         num_subkeys+1));
2698                                 SAFE_FREE( subkeys );
2699                                 return 0;
2700                         }
2701                         
2702                         subkeys_ptr = ptr;
2703                         fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2704                         num_subkeys++;
2705                 }
2706                 
2707         }
2708         
2709         /* return error if the key was not found */
2710         
2711         if ( i == data->num_keys )
2712                 return -1;
2713         
2714 done:
2715         /* tag off the end */
2716         
2717         if (num_subkeys)
2718                 fstrcpy(subkeys_ptr[num_subkeys], "" );
2719         
2720         *subkeys = subkeys_ptr;
2721
2722         return num_subkeys;
2723 }
2724
2725 #ifdef HAVE_ADS
2726 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name, 
2727                             const char *sz)
2728 {
2729         smb_ucs2_t conv_str[1024];
2730         size_t str_size;
2731
2732         regval_ctr_delvalue(ctr, val_name);
2733         str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2734                              STR_TERMINATE | STR_NOALIGN);
2735         regval_ctr_addvalue(ctr, val_name, REG_SZ, 
2736                             (char *) conv_str, str_size);
2737 }
2738
2739 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name, 
2740                                uint32 dword)
2741 {
2742         regval_ctr_delvalue(ctr, val_name);
2743         regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2744                             (char *) &dword, sizeof(dword));
2745 }
2746
2747 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2748                               BOOL b)
2749 {
2750         uint8 bin_bool = (b ? 1 : 0);
2751         regval_ctr_delvalue(ctr, val_name);
2752         regval_ctr_addvalue(ctr, val_name, REG_BINARY, 
2753                             (char *) &bin_bool, sizeof(bin_bool));
2754 }
2755
2756 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2757                                          const char *multi_sz)
2758 {
2759         smb_ucs2_t *conv_strs = NULL;
2760         size_t str_size;
2761
2762         /* a multi-sz has to have a null string terminator, i.e., the last
2763            string must be followed by two nulls */
2764         str_size = strlen(multi_sz) + 2;
2765         conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2766         if (!conv_strs) {
2767                 return;
2768         }
2769
2770         /* Change to byte units. */
2771         str_size *= sizeof(smb_ucs2_t);
2772         push_ucs2(NULL, conv_strs, multi_sz, str_size, 
2773                   STR_TERMINATE | STR_NOALIGN);
2774
2775         regval_ctr_delvalue(ctr, val_name);
2776         regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ, 
2777                             (char *) conv_strs, str_size);      
2778         safe_free(conv_strs);
2779         
2780 }
2781
2782 /****************************************************************************
2783  * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2784  *
2785  * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2786  * @return BOOL indicating success or failure
2787  ***************************************************************************/
2788
2789 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2790 {
2791         REGVAL_CTR *ctr = NULL;
2792         fstring longname;
2793         fstring dnssuffix;
2794         char *allocated_string = NULL;
2795         const char *ascii_str;
2796         int i;
2797
2798         if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2799                 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2800         ctr = &info2->data.keys[i].values;
2801
2802         map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2803         map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2804
2805         /* we make the assumption that the netbios name is the same 
2806            as the DNS name sinc ethe former will be what we used to 
2807            join the domain */
2808
2809         if ( get_mydnsdomname( dnssuffix ) )
2810                 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2811         else
2812                 fstrcpy( longname, global_myname() );
2813                 
2814         map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2815
2816         asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2817         map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2818         SAFE_FREE(allocated_string);
2819
2820         map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2821         map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2822         map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2823         map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2824         map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2825         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2826         map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2827         map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2828         map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2829
2830         map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2831                           (info2->attributes & 
2832                            PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2833
2834         switch (info2->attributes & 0x3) {
2835         case 0:
2836                 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2837                 break;
2838         case 1:
2839                 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2840                 break;
2841         case 2:
2842                 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2843                 break;
2844         default:
2845                 ascii_str = "unknown";
2846         }
2847         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2848
2849         return True;
2850 }
2851
2852 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2, 
2853                                struct uuid guid)
2854 {
2855         int i;
2856         REGVAL_CTR *ctr=NULL;
2857
2858         /* find the DsSpooler key */
2859         if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2860                 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2861         ctr = &info2->data.keys[i].values;
2862
2863         regval_ctr_delvalue(ctr, "objectGUID");
2864         regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY, 
2865                             (char *) &guid, sizeof(struct uuid));       
2866 }
2867
2868 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2869                                      NT_PRINTER_INFO_LEVEL *printer)
2870 {
2871         ADS_STATUS ads_rc;
2872         void *res;
2873         char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2874         char *srv_dn_utf8, **srv_cn_utf8;
2875         TALLOC_CTX *ctx;
2876         ADS_MODLIST mods;
2877         const char *attrs[] = {"objectGUID", NULL};
2878         struct uuid guid;
2879         WERROR win_rc = WERR_OK;
2880
2881         DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
2882
2883         /* figure out where to publish */
2884         ads_find_machine_acct(ads, &res, global_myname());
2885
2886         /* We use ldap_get_dn here as we need the answer
2887          * in utf8 to call ldap_explode_dn(). JRA. */
2888
2889         srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2890         if (!srv_dn_utf8) {
2891                 ads_destroy(&ads);
2892                 return WERR_SERVER_UNAVAILABLE;
2893         }
2894         ads_msgfree(ads, res);
2895         srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2896         if (!srv_cn_utf8) {
2897                 ldap_memfree(srv_dn_utf8);
2898                 ads_destroy(&ads);
2899                 return WERR_SERVER_UNAVAILABLE;
2900         }
2901         /* Now convert to CH_UNIX. */
2902         if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
2903                 ldap_memfree(srv_dn_utf8);
2904                 ldap_memfree(srv_cn_utf8);
2905                 ads_destroy(&ads);
2906                 return WERR_SERVER_UNAVAILABLE;
2907         }
2908         if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
2909                 ldap_memfree(srv_dn_utf8);
2910                 ldap_memfree(srv_cn_utf8);
2911                 ads_destroy(&ads);
2912                 SAFE_FREE(srv_dn);
2913                 return WERR_SERVER_UNAVAILABLE;
2914         }
2915
2916         ldap_memfree(srv_dn_utf8);
2917         ldap_memfree(srv_cn_utf8);
2918
2919         asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0, 
2920                  printer->info_2->sharename, srv_dn);
2921
2922         SAFE_FREE(srv_dn);
2923         SAFE_FREE(srv_cn_0);
2924
2925         /* build the ads mods */
2926         ctx = talloc_init("nt_printer_publish_ads");
2927         mods = ads_init_mods(ctx);
2928
2929         get_local_printer_publishing_data(ctx, &mods, 
2930                                           &printer->info_2->data);
2931         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, 
2932                     printer->info_2->sharename);
2933
2934         /* publish it */
2935         ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
2936         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
2937                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2938
2939         if (!ADS_ERR_OK(ads_rc))
2940                 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
2941         
2942         talloc_destroy(ctx);
2943
2944         /* retreive the guid and store it locally */
2945         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2946                 ZERO_STRUCT(guid);
2947                 ads_pull_guid(ads, res, &guid);
2948                 ads_msgfree(ads, res);
2949                 store_printer_guid(printer->info_2, guid);
2950                 win_rc = mod_a_printer(printer, 2);
2951         } 
2952
2953         SAFE_FREE(prt_dn);
2954         return win_rc;
2955 }
2956
2957 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
2958                                        NT_PRINTER_INFO_LEVEL *printer)
2959 {
2960         ADS_STATUS ads_rc;
2961         void *res;
2962         char *prt_dn = NULL;
2963
2964         DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
2965
2966         /* remove the printer from the directory */
2967         ads_rc = ads_find_printer_on_server(ads, &res, 
2968                             printer->info_2->sharename, global_myname());
2969
2970         if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2971                 prt_dn = ads_get_dn(ads, res);
2972                 ads_rc = ads_del_dn(ads, prt_dn);
2973                 ads_memfree(ads, prt_dn);
2974         }
2975
2976         ads_msgfree(ads, res);
2977         return WERR_OK;
2978 }
2979
2980 /****************************************************************************
2981  * Publish a printer in the directory
2982  *
2983  * @param snum describing printer service
2984  * @return WERROR indicating status of publishing
2985  ***************************************************************************/
2986
2987 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2988 {
2989         ADS_STATUS ads_rc;
2990         ADS_STRUCT *ads = NULL;
2991         NT_PRINTER_INFO_LEVEL *printer = NULL;
2992         WERROR win_rc;
2993
2994         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2995         if (!W_ERROR_IS_OK(win_rc))
2996                 goto done;
2997
2998         switch (action) {
2999         case SPOOL_DS_PUBLISH:
3000         case SPOOL_DS_UPDATE:
3001                 /* set the DsSpooler info and attributes */
3002                 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3003                         win_rc = WERR_NOMEM;
3004                         goto done;
3005                 }
3006
3007                 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3008                 break;
3009         case SPOOL_DS_UNPUBLISH:
3010                 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3011                 break;
3012         default:
3013                 win_rc = WERR_NOT_SUPPORTED;
3014                 goto done;
3015         }
3016
3017         win_rc = mod_a_printer(printer, 2);
3018         if (!W_ERROR_IS_OK(win_rc)) {
3019                 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3020                 goto done;
3021         }
3022
3023         ads = ads_init(NULL, NULL, NULL);
3024         if (!ads) {
3025                 DEBUG(3, ("ads_init() failed\n"));
3026                 win_rc = WERR_SERVER_UNAVAILABLE;
3027                 goto done;
3028         }
3029         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3030         SAFE_FREE(ads->auth.password);
3031         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3032                 NULL, NULL);
3033
3034         /* ads_connect() will find the DC for us */                                         
3035         ads_rc = ads_connect(ads);
3036         if (!ADS_ERR_OK(ads_rc)) {
3037                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3038                 win_rc = WERR_ACCESS_DENIED;
3039                 goto done;
3040         }
3041
3042         switch (action) {
3043         case SPOOL_DS_PUBLISH:
3044         case SPOOL_DS_UPDATE:
3045                 win_rc = nt_printer_publish_ads(ads, printer);
3046                 break;
3047         case SPOOL_DS_UNPUBLISH:
3048                 win_rc = nt_printer_unpublish_ads(ads, printer);
3049                 break;
3050         }
3051
3052 done:
3053         free_a_printer(&printer, 2);
3054         ads_destroy(&ads);
3055         return win_rc;
3056 }
3057
3058 WERROR check_published_printers(void)
3059 {
3060         ADS_STATUS ads_rc;
3061         ADS_STRUCT *ads = NULL;
3062         int snum;
3063         int n_services = lp_numservices();
3064         NT_PRINTER_INFO_LEVEL *printer = NULL;
3065
3066         ads = ads_init(NULL, NULL, NULL);
3067         if (!ads) {
3068                 DEBUG(3, ("ads_init() failed\n"));
3069                 return WERR_SERVER_UNAVAILABLE;
3070         }
3071         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3072         SAFE_FREE(ads->auth.password);
3073         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3074                 NULL, NULL);
3075
3076         /* ads_connect() will find the DC for us */                                         
3077         ads_rc = ads_connect(ads);
3078         if (!ADS_ERR_OK(ads_rc)) {
3079                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3080                 ads_destroy(&ads);
3081                 return WERR_ACCESS_DENIED;
3082         }
3083
3084         for (snum = 0; snum < n_services; snum++) {
3085                 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3086                         continue;
3087
3088                 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3089                                                 lp_servicename(snum))) &&
3090                     (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3091                         nt_printer_publish_ads(ads, printer);
3092
3093                 free_a_printer(&printer, 2);
3094         }
3095
3096         ads_destroy(&ads);
3097         return WERR_OK;
3098 }
3099
3100 BOOL is_printer_published(Printer_entry *print_hnd, int snum, 
3101                           struct uuid *guid)
3102 {
3103         NT_PRINTER_INFO_LEVEL *printer = NULL;
3104         REGVAL_CTR *ctr;
3105         REGISTRY_VALUE *guid_val;
3106         WERROR win_rc;
3107         int i;
3108
3109         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3110
3111         if (!W_ERROR_IS_OK(win_rc) ||
3112             !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3113             ((i = lookup_printerkey(&printer->info_2->data, 
3114                                     SPOOL_DSSPOOLER_KEY)) < 0) ||
3115             !(ctr = &printer->info_2->data.keys[i].values) ||
3116             !(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
3117                 free_a_printer(&printer, 2);
3118                 return False;
3119         }
3120
3121         /* fetching printer guids really ought to be a separate function.. */
3122         if (guid && regval_size(guid_val) == sizeof(struct uuid))
3123                 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
3124
3125         free_a_printer(&printer, 2);
3126         return True;
3127 }
3128 #else
3129 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3130 {
3131         return WERR_OK;
3132 }
3133
3134 WERROR check_published_printers(void)
3135 {
3136         return WERR_OK;
3137 }
3138
3139 BOOL is_printer_published(Printer_entry *print_hnd, int snum, 
3140                           struct uuid *guid)
3141 {
3142         return False;
3143 }
3144 #endif /* HAVE_ADS */
3145
3146 /****************************************************************************
3147  ***************************************************************************/
3148  
3149 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3150 {
3151         NT_PRINTER_DATA *data;
3152         int             i;
3153         int             removed_keys = 0;
3154         int             empty_slot;
3155         
3156         data = &p2->data;
3157         empty_slot = data->num_keys;
3158
3159         if ( !key )
3160                 return WERR_INVALID_PARAM;
3161         
3162         /* remove all keys */
3163
3164         if ( !strlen(key) ) {
3165                 for ( i=0; i<data->num_keys; i++ ) {
3166                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3167                                 data->keys[i].name));
3168                 
3169                         SAFE_FREE( data->keys[i].name );
3170                         regval_ctr_destroy( &data->keys[i].values );
3171                 }
3172         
3173                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3174                         p2->printername ));
3175         
3176                 SAFE_FREE( data->keys );
3177                 ZERO_STRUCTP( data );
3178
3179                 return WERR_OK;
3180         }
3181
3182         /* remove a specific key (and all subkeys) */
3183         
3184         for ( i=0; i<data->num_keys; i++ ) {
3185                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3186                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3187                                 data->keys[i].name));
3188                 
3189                         SAFE_FREE( data->keys[i].name );
3190                         regval_ctr_destroy( &data->keys[i].values );
3191                 
3192                         /* mark the slot as empty */
3193
3194                         ZERO_STRUCTP( &data->keys[i] );
3195                 }
3196         }
3197
3198         /* find the first empty slot */
3199
3200         for ( i=0; i<data->num_keys; i++ ) {
3201                 if ( !data->keys[i].name ) {
3202                         empty_slot = i;
3203                         removed_keys++;
3204                         break;
3205                 }
3206         }
3207
3208         if ( i == data->num_keys )
3209                 /* nothing was removed */
3210                 return WERR_INVALID_PARAM;
3211
3212         /* move everything down */
3213         
3214         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3215                 if ( data->keys[i].name ) {
3216                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) ); 
3217                         ZERO_STRUCTP( &data->keys[i] );
3218                         empty_slot++;
3219                         removed_keys++;
3220                 }
3221         }
3222
3223         /* update count */
3224                 
3225         data->num_keys -= removed_keys;
3226
3227         /* sanity check to see if anything is left */
3228
3229         if ( !data->num_keys ) {
3230                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3231
3232                 SAFE_FREE( data->keys );
3233                 ZERO_STRUCTP( data );
3234         }
3235
3236         return WERR_OK;
3237 }
3238
3239 /****************************************************************************
3240  ***************************************************************************/
3241  
3242 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3243 {
3244         WERROR          result = WERR_OK;
3245         int             key_index;
3246         
3247         /* we must have names on non-zero length */
3248         
3249         if ( !key || !*key|| !value || !*value )
3250                 return WERR_INVALID_NAME;
3251                 
3252         /* find the printer key first */
3253
3254         key_index = lookup_printerkey( &p2->data, key );
3255         if ( key_index == -1 )
3256                 return WERR_OK;
3257         
3258         /* make sure the value exists so we can return the correct error code */
3259         
3260         if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) )
3261                 return WERR_BADFILE;
3262                 
3263         regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
3264         
3265         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3266                 key, value ));
3267         
3268         return result;
3269 }
3270
3271 /****************************************************************************
3272  ***************************************************************************/
3273  
3274 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value, 
3275                            uint32 type, uint8 *data, int real_len )
3276 {
3277         WERROR          result = WERR_OK;
3278         int             key_index;
3279
3280         /* we must have names on non-zero length */
3281         
3282         if ( !key || !*key|| !value || !*value )
3283                 return WERR_INVALID_NAME;
3284                 
3285         /* find the printer key first */
3286         
3287         key_index = lookup_printerkey( &p2->data, key );
3288         if ( key_index == -1 )
3289                 key_index = add_new_printer_key( &p2->data, key );
3290                 
3291         if ( key_index == -1 )
3292                 return WERR_NOMEM;
3293         
3294         regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
3295                 type, (const char *)data, real_len );
3296         
3297         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3298                 key, value, type, real_len  ));
3299         
3300         return result;
3301 }
3302
3303 /****************************************************************************
3304  ***************************************************************************/
3305  
3306 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3307 {
3308         int             key_index;
3309
3310         if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
3311                 return NULL;
3312
3313         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3314                 key, value ));
3315
3316         return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
3317 }
3318
3319 /****************************************************************************
3320  Unpack a list of registry values frem the TDB
3321  ***************************************************************************/
3322  
3323 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3324 {
3325         int             len = 0;
3326         uint32          type;
3327         pstring         string, valuename, keyname;
3328         char            *str;
3329         int             size;
3330         uint8           *data_p;
3331         REGISTRY_VALUE  *regval_p;
3332         int             key_index;
3333         
3334         /* add the "PrinterDriverData" key first for performance reasons */
3335         
3336         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3337
3338         /* loop and unpack the rest of the registry values */
3339         
3340         while ( True ) {
3341         
3342                 /* check to see if there are any more registry values */
3343                 
3344                 regval_p = NULL;
3345                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);         
3346                 if ( !regval_p ) 
3347                         break;
3348
3349                 /* unpack the next regval */
3350                 
3351                 len += tdb_unpack(buf+len, buflen-len, "fdB",
3352                                   string,
3353                                   &type,
3354                                   &size,
3355                                   &data_p);
3356
3357                 /* lookup for subkey names which have a type of REG_NONE */
3358                 /* there's no data with this entry */
3359
3360                 if ( type == REG_NONE ) {
3361                         if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3362                                 add_new_printer_key( printer_data, string );
3363                         continue;
3364                 }
3365         
3366                 /*
3367                  * break of the keyname from the value name.  
3368                  * Valuenames can have embedded '\'s so be careful.
3369                  * only support one level of keys.  See the 
3370                  * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3371                  * -- jerry
3372                  */     
3373                  
3374                 str = strchr_m( string, '\\');
3375                 
3376                 /* Put in "PrinterDriverData" is no key specified */
3377                 
3378                 if ( !str ) {
3379                         pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3380                         pstrcpy( valuename, string );
3381                 }
3382                 else {
3383                         *str = '\0';
3384                         pstrcpy( keyname, string );
3385                         pstrcpy( valuename, str+1 );
3386                 }
3387                         
3388                 /* see if we need a new key */
3389                 
3390                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3391                         key_index = add_new_printer_key( printer_data, keyname );
3392                         
3393                 if ( key_index == -1 ) {
3394                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3395                                 keyname));
3396                         break;
3397                 }
3398                 
3399                 /* add the new value */
3400                 
3401                 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3402
3403                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3404
3405                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3406         }
3407
3408         return len;
3409 }
3410
3411 /****************************************************************************
3412  ***************************************************************************/
3413
3414 static void map_to_os2_driver(fstring drivername)
3415 {
3416         static BOOL initialised=False;
3417         static fstring last_from,last_to;
3418         char *mapfile = lp_os2_driver_map();
3419         char **lines = NULL;
3420         int numlines = 0;
3421         int i;
3422
3423         if (!strlen(drivername))
3424                 return;
3425
3426         if (!*mapfile)
3427                 return;
3428
3429         if (!initialised) {
3430                 *last_from = *last_to = 0;
3431                 initialised = True;
3432         }
3433
3434         if (strequal(drivername,last_from)) {
3435                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3436                 fstrcpy(drivername,last_to);
3437                 return;
3438         }
3439
3440         lines = file_lines_load(mapfile, &numlines);
3441         if (numlines == 0) {
3442                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3443                 return;
3444         }
3445
3446         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3447
3448         for( i = 0; i < numlines; i++) {
3449                 char *nt_name = lines[i];
3450                 char *os2_name = strchr(nt_name,'=');
3451
3452                 if (!os2_name)
3453                         continue;
3454
3455                 *os2_name++ = 0;
3456
3457                 while (isspace(*nt_name))
3458                         nt_name++;
3459
3460                 if (!*nt_name || strchr("#;",*nt_name))
3461                         continue;
3462
3463                 {
3464                         int l = strlen(nt_name);
3465                         while (l && isspace(nt_name[l-1])) {
3466                                 nt_name[l-1] = 0;
3467                                 l--;
3468                         }
3469                 }
3470
3471                 while (isspace(*os2_name))
3472                         os2_name++;
3473
3474                 {
3475                         int l = strlen(os2_name);
3476                         while (l && isspace(os2_name[l-1])) {
3477                                 os2_name[l-1] = 0;
3478                                 l--;
3479                         }
3480                 }
3481
3482                 if (strequal(nt_name,drivername)) {
3483                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3484                         fstrcpy(last_from,drivername);
3485                         fstrcpy(last_to,os2_name);
3486                         fstrcpy(drivername,os2_name);
3487                         file_lines_free(lines);
3488                         return;
3489                 }
3490         }
3491
3492         file_lines_free(lines);
3493 }
3494
3495 /****************************************************************************
3496  Get a default printer info 2 struct.
3497 ****************************************************************************/
3498 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char* sharename)
3499 {
3500         int snum;
3501         NT_PRINTER_INFO_LEVEL_2 info;
3502
3503         ZERO_STRUCT(info);
3504
3505         snum = lp_servicenumber(sharename);
3506
3507         slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
3508         slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s", 
3509                 servername, sharename);
3510         fstrcpy(info.sharename, sharename);
3511         fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3512
3513         /* by setting the driver name to an empty string, a local NT admin
3514            can now run the **local** APW to install a local printer driver
3515            for a Samba shared printer in 2.2.  Without this, drivers **must** be 
3516            installed on the Samba server for NT clients --jerry */
3517 #if 0   /* JERRY --do not uncomment-- */
3518         if (!*info.drivername)
3519                 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3520 #endif
3521
3522
3523         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3524
3525         pstrcpy(info.comment, "");
3526         fstrcpy(info.printprocessor, "winprint");
3527         fstrcpy(info.datatype, "RAW");
3528
3529         info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3530
3531         info.starttime = 0; /* Minutes since 12:00am GMT */
3532         info.untiltime = 0; /* Minutes since 12:00am GMT */
3533         info.priority = 1;
3534         info.default_priority = 1;
3535         info.setuptime = (uint32)time(NULL);
3536
3537         /*
3538          * I changed this as I think it is better to have a generic
3539          * DEVMODE than to crash Win2k explorer.exe   --jerry
3540          * See the HP Deskjet 990c Win2k drivers for an example.
3541          *
3542          * However the default devmode appears to cause problems
3543          * with the HP CLJ 8500 PCL driver.  Hence the addition of
3544          * the "default devmode" parameter   --jerry 22/01/2002
3545          */
3546
3547         if (lp_default_devmode(snum)) {
3548                 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3549                         goto fail;
3550         }
3551         else {
3552                 info.devmode = NULL;
3553         }
3554
3555         /* This will get the current RPC talloc context, but we should be
3556            passing this as a parameter... fixme... JRA ! */
3557
3558         if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3559                 goto fail;
3560
3561         *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3562         if (! *info_ptr) {
3563                 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3564                 goto fail;
3565         }
3566
3567         return WERR_OK;
3568
3569   fail:
3570         if (info.devmode)
3571                 free_nt_devicemode(&info.devmode);
3572         return WERR_ACCESS_DENIED;
3573 }
3574
3575 /****************************************************************************
3576 ****************************************************************************/
3577 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char *sharename)
3578 {
3579         pstring key;
3580         NT_PRINTER_INFO_LEVEL_2 info;
3581         int len = 0;
3582         int snum = lp_servicenumber(sharename);
3583         TDB_DATA kbuf, dbuf;
3584         fstring printername;
3585         char adevice[MAXDEVICENAME];
3586         fstring norm_sharename;
3587                 
3588         ZERO_STRUCT(info);
3589
3590         /* normalize case */
3591         fstrcpy( norm_sharename, sharename );
3592         strlower_m( norm_sharename );
3593
3594         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, norm_sharename);
3595
3596         kbuf.dptr = key;
3597         kbuf.dsize = strlen(key)+1;
3598
3599         dbuf = tdb_fetch(tdb_printers, kbuf);
3600         if (!dbuf.dptr)
3601                 return get_a_printer_2_default(info_ptr, servername, norm_sharename);
3602
3603         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3604                         &info.attributes,
3605                         &info.priority,
3606                         &info.default_priority,
3607                         &info.starttime,
3608                         &info.untiltime,
3609                         &info.status,
3610                         &info.cjobs,
3611                         &info.averageppm,
3612                         &info.changeid,
3613                         &info.c_setprinter,
3614                         &info.setuptime,
3615                         info.servername,
3616                         info.printername,
3617                         info.sharename,
3618                         info.portname,
3619                         info.drivername,
3620                         info.comment,
3621                         info.location,
3622                         info.sepfile,
3623                         info.printprocessor,
3624                         info.datatype,
3625                         info.parameters);
3626
3627         /* Samba has to have shared raw drivers. */
3628         info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3629         info.attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3630
3631         /* Restore the stripped strings. */
3632         slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
3633
3634         if ( lp_force_printername(snum) )
3635                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, norm_sharename );
3636         else 
3637                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info.printername);
3638
3639         fstrcpy(info.printername, printername);
3640
3641         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3642
3643         /*
3644          * Some client drivers freak out if there is a NULL devmode
3645          * (probably the driver is not checking before accessing 
3646          * the devmode pointer)   --jerry
3647          *
3648          * See comments in get_a_printer_2_default()
3649          */
3650
3651         if (lp_default_devmode(snum) && !info.devmode) {
3652                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3653                         printername));
3654                 info.devmode = construct_nt_devicemode(printername);
3655         }
3656
3657         slprintf( adevice, sizeof(adevice), "%s", info.printername );
3658         if (info.devmode) {
3659                 fstrcpy(info.devmode->devicename, adevice);     
3660         }
3661
3662         len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3663
3664         /* This will get the current RPC talloc context, but we should be
3665            passing this as a parameter... fixme... JRA ! */
3666
3667         nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3668
3669         /* Fix for OS/2 drivers. */
3670
3671         if (get_remote_arch() == RA_OS2)
3672                 map_to_os2_driver(info.drivername);
3673
3674         SAFE_FREE(dbuf.dptr);
3675         *info_ptr=memdup(&info, sizeof(info));
3676
3677         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3678                  sharename, info.printername, info.drivername));
3679
3680         return WERR_OK; 
3681 }
3682
3683 /****************************************************************************
3684  Debugging function, dump at level 6 the struct in the logs.
3685 ****************************************************************************/
3686 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3687 {
3688         uint32 result;
3689         NT_PRINTER_INFO_LEVEL_2 *info2;
3690         
3691         DEBUG(106,("Dumping printer at level [%d]\n", level));
3692         
3693         switch (level) {
3694                 case 2:
3695                 {
3696                         if (printer->info_2 == NULL)
3697                                 result=5;
3698                         else
3699                         {
3700                                 info2=printer->info_2;
3701                         
3702                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3703                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3704                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3705                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3706                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3707                                 DEBUGADD(106,("status:[%d]\n", info2->status));
3708                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3709                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3710                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3711                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3712                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3713
3714                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3715                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3716                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3717                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3718                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3719                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3720                                 DEBUGADD(106,("location:[%s]\n", info2->location));
3721                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3722                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3723                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3724                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3725                                 result=0;
3726                         }
3727                         break;
3728                 }
3729                 default:
3730                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3731                         result=1;
3732                         break;
3733         }
3734         
3735         return result;
3736 }
3737
3738 /****************************************************************************
3739  Update the changeid time.
3740  This is SO NASTY as some drivers need this to change, others need it
3741  static. This value will change every second, and I must hope that this
3742  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3743  UTAH ! JRA.
3744 ****************************************************************************/
3745
3746 static uint32 rev_changeid(void)
3747 {
3748         struct timeval tv;
3749
3750         get_process_uptime(&tv);
3751
3752 #if 1   /* JERRY */
3753         /* Return changeid as msec since spooler restart */
3754         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3755 #else
3756         /*
3757          * This setting seems to work well but is too untested
3758          * to replace the above calculation.  Left in for experiementation
3759          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
3760          */
3761         return tv.tv_sec * 10 + tv.tv_usec / 100000;
3762 #endif
3763 }
3764
3765 /********************************************************************
3766  Send a message to all smbds about the printer that just changed
3767  ********************************************************************/
3768  
3769 static BOOL send_printer_mod_msg( char* printername )
3770 {
3771         int len = strlen(printername);
3772         
3773         if (!len)
3774                 return False;
3775
3776         DEBUG(10,("send_printer_mod_msg: Sending message about printer change [%s]\n",
3777                 printername));
3778                 
3779         /* spam everyone that we just changed this printer */
3780         
3781         message_send_all( conn_tdb_ctx(), MSG_PRINTER_MOD, printername, len+1, False, NULL );
3782
3783         return True;
3784 }
3785
3786 /*
3787  * The function below are the high level ones.
3788  * only those ones must be called from the spoolss code.
3789  * JFM.
3790  */
3791
3792 /****************************************************************************
3793  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3794 ****************************************************************************/
3795
3796 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3797 {
3798         WERROR result;
3799         
3800         dump_a_printer(printer, level); 
3801         
3802         /* 
3803          * invalidate cache for all open handles to this printer.
3804          * cache for a given handle will be updated on the next 
3805          * get_a_printer() 
3806          */
3807          
3808         invalidate_printer_hnd_cache( printer->info_2->sharename );
3809         send_printer_mod_msg( printer->info_2->sharename );
3810         
3811         switch (level) {
3812                 case 2:
3813                 {
3814                         /*
3815                          * Update the changestamp.  Emperical tests show that the
3816                          * ChangeID is always updated,but c_setprinter is  
3817                          *  global spooler variable (not per printer).
3818                          */
3819
3820                         /* ChangeID **must** be increasing over the lifetime
3821                            of client's spoolss service in order for the
3822                            client's cache to show updates */
3823
3824                         printer->info_2->changeid = rev_changeid();
3825
3826                         /*
3827                          * Because one day someone will ask:
3828                          * NT->NT       An admin connection to a remote
3829                          *              printer show changes imeediately in
3830                          *              the properities dialog
3831                          *      
3832                          *              A non-admin connection will only show the
3833                          *              changes after viewing the properites page
3834                          *              2 times.  Seems to be related to a
3835                          *              race condition in the client between the spooler
3836                          *              updating the local cache and the Explorer.exe GUI
3837                          *              actually displaying the properties.
3838                          *
3839                          *              This is fixed in Win2k.  admin/non-admin
3840                          *              connections both display changes immediately.
3841                          *
3842                          * 14/12/01     --jerry
3843                          */
3844
3845                         result=update_a_printer_2(printer->info_2);
3846                         
3847                         break;
3848                 }
3849                 default:
3850                         result=WERR_UNKNOWN_LEVEL;
3851                         break;
3852         }
3853         
3854         return result;
3855 }
3856
3857 /****************************************************************************
3858  Initialize printer devmode & data with previously saved driver init values.
3859 ****************************************************************************/
3860
3861 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3862 {
3863         int                     len = 0;
3864         pstring                 key;
3865         TDB_DATA                kbuf, dbuf;
3866         NT_PRINTER_INFO_LEVEL_2 info;
3867
3868
3869         ZERO_STRUCT(info);
3870
3871         /*
3872          * Delete any printer data 'values' already set. When called for driver
3873          * replace, there will generally be some, but during an add printer, there
3874          * should not be any (if there are delete them).
3875          */
3876          
3877         delete_all_printer_data( info_ptr, "" );
3878         
3879         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3880
3881         kbuf.dptr = key;
3882         kbuf.dsize = strlen(key)+1;
3883
3884         dbuf = tdb_fetch(tdb_drivers, kbuf);
3885         if (!dbuf.dptr) {
3886                 /*
3887                  * When changing to a driver that has no init info in the tdb, remove
3888                  * the previous drivers init info and leave the new on blank.
3889                  */
3890                 free_nt_devicemode(&info_ptr->devmode);
3891                 return False;
3892         }
3893         
3894         /*
3895          * Get the saved DEVMODE..
3896          */
3897          
3898         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3899
3900         /*
3901          * The saved DEVMODE contains the devicename from the printer used during
3902          * the initialization save. Change it to reflect the new printer.
3903          */
3904          
3905         if ( info.devmode ) {
3906                 ZERO_STRUCT(info.devmode->devicename);
3907                 fstrcpy(info.devmode->devicename, info_ptr->printername);
3908         }
3909
3910         /*
3911          * NT/2k does not change out the entire DeviceMode of a printer
3912          * when changing the driver.  Only the driverextra, private, & 
3913          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
3914          *
3915          * Later examination revealed that Windows NT/2k does reset the
3916          * the printer's device mode, bit **only** when you change a 
3917          * property of the device mode such as the page orientation.
3918          * --jerry
3919          */
3920
3921
3922         /* Bind the saved DEVMODE to the new the printer */
3923          
3924         free_nt_devicemode(&info_ptr->devmode);
3925         info_ptr->devmode = info.devmode;
3926
3927         DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3928                 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3929
3930         /* Add the printer data 'values' to the new printer */
3931          
3932         len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3933         
3934
3935         SAFE_FREE(dbuf.dptr);
3936
3937         return True;    
3938 }
3939
3940 /****************************************************************************
3941  Initialize printer devmode & data with previously saved driver init values.
3942  When a printer is created using AddPrinter, the drivername bound to the
3943  printer is used to lookup previously saved driver initialization info, which
3944  is bound to the new printer.
3945 ****************************************************************************/
3946
3947 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3948 {
3949         BOOL result = False;
3950         
3951         switch (level) {
3952                 case 2:
3953                         result = set_driver_init_2(printer->info_2);
3954                         break;
3955                         
3956                 default:
3957                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
3958                                 level));
3959                         break;
3960         }
3961         
3962         return result;
3963 }
3964
3965 /****************************************************************************
3966  Delete driver init data stored for a specified driver
3967 ****************************************************************************/
3968
3969 BOOL del_driver_init(char *drivername)
3970 {
3971         pstring key;
3972         TDB_DATA kbuf;
3973
3974         if (!drivername || !*drivername) {
3975                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3976                 return False;
3977         }
3978
3979         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3980
3981         kbuf.dptr = key;
3982         kbuf.dsize = strlen(key)+1;
3983
3984         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3985
3986         return (tdb_delete(tdb_drivers, kbuf) == 0);
3987 }
3988
3989 /****************************************************************************
3990  Pack up the DEVMODE and values for a printer into a 'driver init' entry 
3991  in the tdb. Note: this is different from the driver entry and the printer
3992  entry. There should be a single driver init entry for each driver regardless
3993  of whether it was installed from NT or 2K. Technically, they should be
3994  different, but they work out to the same struct.
3995 ****************************************************************************/
3996
3997 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3998 {
3999         pstring key;
4000         char *buf;
4001         int buflen, len, ret;
4002         TDB_DATA kbuf, dbuf;
4003
4004         buf = NULL;
4005         buflen = 0;
4006
4007  again: 
4008         len = 0;
4009         len += pack_devicemode(info->devmode, buf+len, buflen-len);
4010
4011         len += pack_values( &info->data, buf+len, buflen-len );
4012
4013         if (buflen < len) {
4014                 char *tb;
4015
4016                 tb = (char *)SMB_REALLOC(buf, len);
4017                 if (!tb) {
4018                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4019                         ret = -1;
4020                         goto done;
4021                 }
4022                 else
4023                         buf = tb;
4024                 buflen = len;
4025                 goto again;
4026         }
4027
4028         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4029
4030         kbuf.dptr = key;
4031         kbuf.dsize = strlen(key)+1;
4032         dbuf.dptr = buf;
4033         dbuf.dsize = len;
4034
4035         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
4036
4037 done:
4038         if (ret == -1)
4039                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4040
4041         SAFE_FREE(buf);
4042
4043         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4044                  info->sharename, info->drivername));
4045
4046         return ret;
4047 }
4048
4049 /****************************************************************************
4050  Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4051 ****************************************************************************/
4052
4053 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4054 {
4055         uint32 result;
4056         
4057         dump_a_printer(printer, level); 
4058         
4059         switch (level) {
4060                 case 2:
4061                         result = update_driver_init_2(printer->info_2);
4062                         break;
4063                 default:
4064                         result = 1;
4065                         break;
4066         }
4067         
4068         return result;
4069 }
4070
4071 /****************************************************************************
4072  Convert the printer data value, a REG_BINARY array, into an initialization 
4073  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4074  got to keep the endians happy :).
4075 ****************************************************************************/
4076
4077 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4078 {
4079         BOOL       result = False;
4080         prs_struct ps;
4081         DEVICEMODE devmode;
4082
4083         ZERO_STRUCT(devmode);
4084
4085         prs_init(&ps, 0, ctx, UNMARSHALL);
4086         ps.data_p      = (char *)data;
4087         ps.buffer_size = data_len;
4088
4089         if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4090                 result = convert_devicemode("", &devmode, &nt_devmode);
4091         else
4092                 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4093
4094         return result;
4095 }
4096
4097 /****************************************************************************
4098  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4099
4100  1. Use the driver's config DLL to this UNC printername and:
4101     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4102     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4103  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4104
4105  The last step triggers saving the "driver initialization" information for
4106  this printer into the tdb. Later, new printers that use this driver will
4107  have this initialization information bound to them. This simulates the
4108  driver initialization, as if it had run on the Samba server (as it would
4109  have done on NT).
4110
4111  The Win32 client side code requirement sucks! But until we can run arbitrary
4112  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4113  
4114  It would have been easier to use SetPrinter because all the UNMARSHALLING of
4115  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4116  about it and you will realize why.  JRR 010720
4117 ****************************************************************************/
4118
4119 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4120 {
4121         WERROR        status       = WERR_OK;
4122         TALLOC_CTX    *ctx         = NULL;
4123         NT_DEVICEMODE *nt_devmode  = NULL;
4124         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4125         
4126         /*
4127          * When the DEVMODE is already set on the printer, don't try to unpack it.
4128          */
4129         DEBUG(8,("save_driver_init_2: Enter...\n"));
4130         
4131         if ( !printer->info_2->devmode && data_len ) {
4132                 /*
4133                  * Set devmode on printer info, so entire printer initialization can be
4134                  * saved to tdb.
4135                  */
4136
4137                 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4138                         return WERR_NOMEM;
4139
4140                 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4141                         status = WERR_NOMEM;
4142                         goto done;
4143                 }
4144         
4145                 ZERO_STRUCTP(nt_devmode);
4146
4147                 /*
4148                  * The DEVMODE is held in the 'data' component of the param in raw binary.
4149                  * Convert it to to a devmode structure
4150                  */
4151                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4152                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4153                         status = WERR_INVALID_PARAM;
4154                         goto done;
4155                 }
4156
4157                 printer->info_2->devmode = nt_devmode;
4158         }
4159
4160         /*
4161          * Pack up and add (or update) the DEVMODE and any current printer data to
4162          * a 'driver init' element in the tdb
4163          * 
4164          */
4165
4166         if ( update_driver_init(printer, 2) != 0 ) {
4167                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4168                 status = WERR_NOMEM;
4169                 goto done;
4170         }
4171         
4172         /*
4173          * If driver initialization info was successfully saved, set the current 
4174          * printer to match it. This allows initialization of the current printer 
4175          * as well as the driver.
4176          */
4177         status = mod_a_printer(printer, 2);
4178         if (!W_ERROR_IS_OK(status)) {
4179                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4180                                   printer->info_2->printername));
4181         }
4182         
4183   done:
4184         talloc_destroy(ctx);
4185         free_nt_devicemode( &nt_devmode );
4186         
4187         printer->info_2->devmode = tmp_devmode;
4188
4189         return status;
4190 }
4191
4192 /****************************************************************************
4193  Update the driver init info (DEVMODE and specifics) for a printer
4194 ****************************************************************************/
4195
4196 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4197 {
4198         WERROR status = WERR_OK;
4199         
4200         switch (level) {
4201                 case 2:
4202                         status = save_driver_init_2( printer, data, data_len );
4203                         break;
4204                 default:
4205                         status = WERR_UNKNOWN_LEVEL;
4206                         break;
4207         }
4208         
4209         return status;
4210 }
4211
4212 /****************************************************************************
4213  Deep copy a NT_PRINTER_DATA
4214 ****************************************************************************/
4215
4216 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
4217 {
4218         int i, j, num_vals, new_key_index;
4219         REGVAL_CTR *src_key, *dst_key;
4220         
4221         if ( !dst || !src )
4222                 return NT_STATUS_NO_MEMORY;
4223         
4224         for ( i=0; i<src->num_keys; i++ ) {
4225                            
4226                 /* create a new instance of the printerkey in the destination 
4227                    printer_data object */
4228                    
4229                 new_key_index = add_new_printer_key( dst, src->keys[i].name );
4230                 dst_key = &dst->keys[new_key_index].values;
4231
4232                 src_key = &src->keys[i].values;
4233                 num_vals = regval_ctr_numvals( src_key );
4234                 
4235                 /* dup the printer entire printer key */
4236                 
4237                 for ( j=0; j<num_vals; j++ ) {
4238                         regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
4239                 }
4240         }
4241                 
4242         return NT_STATUS_OK;
4243 }
4244
4245 /****************************************************************************
4246  Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
4247  Caller must free.
4248 ****************************************************************************/
4249
4250 NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
4251 {
4252         NT_PRINTER_INFO_LEVEL_2 *copy;
4253         
4254         if ( !printer )
4255                 return NULL;
4256         
4257         if ( !(copy = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL_2)) )
4258                 return NULL;
4259                 
4260         memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
4261         
4262         /* malloc()'d members copied here */
4263         
4264         copy->devmode = dup_nt_devicemode( printer->devmode );  
4265
4266         ZERO_STRUCT( copy->data );
4267         copy_printer_data( &copy->data, &printer->data );
4268         
4269         /* this is talloc()'d; very ugly that we have a structure that 
4270            is half malloc()'d and half talloc()'d but that is the way 
4271            that the PRINTER_INFO stuff is written right now.  --jerry  */
4272            
4273         copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
4274                 
4275         return copy;
4276 }
4277
4278 /****************************************************************************
4279  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4280
4281  Previously the code had a memory allocation problem because it always
4282  used the TALLOC_CTX from the Printer_entry*.   This context lasts 
4283  as a long as the original handle is open.  So if the client made a lot 
4284  of getprinter[data]() calls, the memory usage would climb.  Now we use
4285  a short lived TALLOC_CTX for printer_info_2 objects returned.  We 
4286  still use the Printer_entry->ctx for maintaining the cache copy though
4287  since that object must live as long as the handle by definition.  
4288                                                     --jerry
4289
4290 ****************************************************************************/
4291
4292 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, 
4293                         const char *sharename)
4294 {
4295         WERROR result;
4296         NT_PRINTER_INFO_LEVEL *printer = NULL;
4297         fstring servername;
4298         
4299         *pp_printer = NULL;
4300
4301         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4302
4303         switch (level) {
4304                 case 2:
4305                         if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
4306                                 DEBUG(0,("get_a_printer: malloc fail.\n"));
4307                                 return WERR_NOMEM;
4308                         }
4309                         ZERO_STRUCTP(printer);
4310
4311                         if ( print_hnd ) 
4312                                 fstrcpy( servername, print_hnd->servername );
4313                         else {
4314                                 fstrcpy( servername, "%L" );
4315                                 standard_sub_basic( "", servername, sizeof(servername)-1 );
4316                         }
4317                         
4318                         /* 
4319                          * check for cache first.  A Printer handle cannot changed
4320                          * to another printer object so we only check that the printer 
4321                          * is actually for a printer and that the printer_info pointer 
4322                          * is valid
4323                          */
4324                         if ( print_hnd 
4325                                 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER) 
4326                                 && print_hnd->printer_info )
4327                         {
4328                                 /* get_talloc_ctx() works here because we need a short 
4329                                    lived talloc context */
4330
4331                                 if ( !(printer->info_2 = dup_printer_2(get_talloc_ctx(), print_hnd->printer_info->info_2)) ) 
4332                                 {
4333                                         DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
4334                                         
4335                                         SAFE_FREE(printer);
4336                                         return WERR_NOMEM;
4337                                 }
4338                                 
4339                                 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
4340                                 
4341                                 *pp_printer = printer;                          
4342                                 result = WERR_OK;
4343                                 
4344                                 break;
4345                         }
4346
4347                         /* no cache for this handle; see if we can match one from another handle.
4348                            Make sure to use a short lived talloc ctx */
4349
4350                         if ( print_hnd )
4351                                 result = find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer->info_2, servername, sharename);
4352                         
4353                         /* fail to disk if we don't have it with any open handle */
4354
4355                         if ( !print_hnd || !W_ERROR_IS_OK(result) )
4356                                 result = get_a_printer_2(&printer->info_2, servername, sharename );
4357                         
4358                         /* we have a new printer now.  Save it with this handle */
4359                         
4360                         if ( W_ERROR_IS_OK(result) ) {
4361                                 dump_a_printer(printer, level);
4362                                         
4363                                 /* save a copy in cache */
4364                                 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
4365                                         if ( !print_hnd->printer_info )
4366                                                 print_hnd->printer_info = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL);
4367
4368                                         if ( print_hnd->printer_info ) {
4369                                                 /* make sure to use the handle's talloc ctx here since 
4370                                                    the printer_2 object must last until the handle is closed */
4371
4372                                                 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
4373                                                 
4374                                                 /* don't fail the lookup just because the cache update failed */
4375                                                 if ( !print_hnd->printer_info->info_2 )
4376                                                         DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4377                                         }
4378                                 }
4379                                 *pp_printer = printer;  
4380                         }
4381                         else
4382                                 SAFE_FREE(printer);
4383                         
4384                         break;
4385                         
4386                 default:
4387                         result=WERR_UNKNOWN_LEVEL;
4388                         break;
4389         }
4390         
4391         DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
4392
4393         return result;
4394 }
4395
4396 /****************************************************************************
4397  Deletes a NT_PRINTER_INFO_LEVEL struct.
4398 ****************************************************************************/
4399
4400 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4401 {
4402         uint32 result;
4403         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4404
4405         DEBUG(104,("freeing a printer at level [%d]\n", level));
4406
4407         if (printer == NULL)
4408                 return 0;
4409         
4410         switch (level) {
4411                 case 2:
4412                         if (printer->info_2 != NULL) {
4413                                 free_nt_printer_info_level_2(&printer->info_2);
4414                                 result=0;
4415                         } else
4416                                 result=4;
4417                         break;
4418
4419                 default:
4420                         result=1;
4421                         break;
4422         }
4423
4424         SAFE_FREE(*pp_printer);
4425         return result;
4426 }
4427
4428 /****************************************************************************
4429 ****************************************************************************/
4430 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4431 {
4432         uint32 result;
4433         DEBUG(104,("adding a printer at level [%d]\n", level));
4434         dump_a_printer_driver(driver, level);
4435         
4436         switch (level) {
4437                 case 3:
4438                         result=add_a_printer_driver_3(driver.info_3);
4439                         break;
4440
4441                 case 6:
4442                         result=add_a_printer_driver_6(driver.info_6);
4443                         break;
4444
4445                 default:
4446                         result=1;
4447                         break;
4448         }
4449         
4450         return result;
4451 }
4452 /****************************************************************************
4453 ****************************************************************************/
4454
4455 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4456                             fstring drivername, const char *architecture, uint32 version)
4457 {
4458         WERROR result;
4459         
4460         switch (level) {
4461                 case 3:
4462                         /* Sometime we just want any version of the driver */
4463                         
4464                         if ( version == DRIVER_ANY_VERSION ) {
4465                                 /* look for Win2k first and then for NT4 */
4466                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4467                                                 architecture, 3);
4468                                                 
4469                                 if ( !W_ERROR_IS_OK(result) ) {
4470                                         result = get_a_printer_driver_3( &driver->info_3, 
4471                                                         drivername, architecture, 2 );
4472                                 }
4473                         } else {
4474                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4475                                         architecture, version);                         
4476                         }
4477                         break;
4478                         
4479                 default:
4480                         result=W_ERROR(1);
4481                         break;
4482         }
4483         
4484         if (W_ERROR_IS_OK(result))
4485                 dump_a_printer_driver(*driver, level);
4486                 
4487         return result;
4488 }
4489
4490 /****************************************************************************
4491 ****************************************************************************/
4492 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4493 {
4494         uint32 result;
4495         
4496         switch (level) {
4497                 case 3:
4498                 {
4499                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4500                         if (driver.info_3 != NULL)
4501                         {
4502                                 info3=driver.info_3;
4503                                 SAFE_FREE(info3->dependentfiles);
4504                                 ZERO_STRUCTP(info3);
4505                                 SAFE_FREE(info3);
4506                                 result=0;
4507                         } else {
4508                                 result=4;
4509                         }
4510                         break;
4511                 }
4512                 case 6:
4513                 {
4514                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4515                         if (driver.info_6 != NULL) {
4516                                 info6=driver.info_6;
4517                                 SAFE_FREE(info6->dependentfiles);
4518                                 SAFE_FREE(info6->previousnames);
4519                                 ZERO_STRUCTP(info6);
4520                                 SAFE_FREE(info6);
4521                                 result=0;
4522                         } else {
4523                                 result=4;
4524                         }
4525                         break;
4526                 }
4527                 default:
4528                         result=1;
4529                         break;
4530         }
4531         return result;
4532 }
4533
4534
4535 /****************************************************************************
4536   Determine whether or not a particular driver is currently assigned
4537   to a printer
4538 ****************************************************************************/
4539
4540 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4541 {
4542         int snum;
4543         int n_services = lp_numservices();
4544         NT_PRINTER_INFO_LEVEL *printer = NULL;
4545         BOOL in_use = False;
4546
4547         if ( !info_3 ) 
4548                 return False;
4549
4550         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4551         
4552         /* loop through the printers.tdb and check for the drivername */
4553         
4554         for (snum=0; snum<n_services && !in_use; snum++) {
4555                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4556                         continue;
4557                 
4558                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4559                         continue;
4560                 
4561                 if ( strequal(info_3->name, printer->info_2->drivername) ) 
4562                         in_use = True;
4563                 
4564                 free_a_printer( &printer, 2 );
4565         }
4566         
4567         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4568         
4569         if ( in_use ) {
4570                 NT_PRINTER_DRIVER_INFO_LEVEL d;
4571                 WERROR werr;
4572                 
4573                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4574                 
4575                 /* we can still remove the driver if there is one of 
4576                    "Windows NT x86" version 2 or 3 left */
4577                    
4578                 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4579                         werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );                       
4580                 }
4581                 else {
4582                         switch ( info_3->cversion ) {
4583                         case 2:
4584                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4585                                 break;
4586                         case 3: 
4587                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4588                                 break;
4589                         default:
4590                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n", 
4591                                         info_3->cversion));
4592                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4593                                 break;
4594                         }
4595                 }
4596
4597                 /* now check the error code */
4598                                 
4599                 if ( W_ERROR_IS_OK(werr) ) {
4600                         /* it's ok to remove the driver, we have other architctures left */
4601                         in_use = False;
4602                         free_a_printer_driver( d, 3 );
4603                 }
4604         }
4605         
4606         /* report that the driver is not in use by default */
4607         
4608         return in_use;
4609 }
4610
4611
4612 /**********************************************************************
4613  Check to see if a ogiven file is in use by *info
4614  *********************************************************************/
4615  
4616 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4617 {
4618         int i = 0;
4619         
4620         if ( !info )
4621                 return False;
4622                 
4623         if ( strequal(file, info->driverpath) )
4624                 return True;
4625
4626         if ( strequal(file, info->datafile) )
4627                 return True;
4628
4629         if ( strequal(file, info->configfile) )
4630                 return True;
4631
4632         if ( strequal(file, info->helpfile) )
4633                 return True;
4634         
4635         /* see of there are any dependent files to examine */
4636         
4637         if ( !info->dependentfiles )
4638                 return False;
4639         
4640         while ( *info->dependentfiles[i] ) {
4641                 if ( strequal(file, info->dependentfiles[i]) )
4642                         return True;
4643                 i++;
4644         }
4645         
4646         return False;
4647
4648 }
4649
4650 /**********************************************************************
4651  Utility function to remove the dependent file pointed to by the 
4652  input parameter from the list 
4653  *********************************************************************/
4654
4655 static void trim_dependent_file( fstring files[], int idx )
4656 {
4657         
4658         /* bump everything down a slot */
4659
4660         while( *files[idx+1] ) {
4661                 fstrcpy( files[idx], files[idx+1] );
4662                 idx++;
4663         }
4664         
4665         *files[idx] = '\0';
4666
4667         return; 
4668 }
4669
4670 /**********************************************************************
4671  Check if any of the files used by src are also used by drv 
4672  *********************************************************************/
4673
4674 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, 
4675                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4676 {
4677         BOOL    in_use = False;
4678         int     i = 0;
4679         
4680         if ( !src || !drv )
4681                 return False;
4682                 
4683         /* check each file.  Remove it from the src structure if it overlaps */
4684         
4685         if ( drv_file_in_use(src->driverpath, drv) ) {
4686                 in_use = True;
4687                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4688                 fstrcpy( src->driverpath, "" );
4689         }
4690                 
4691         if ( drv_file_in_use(src->datafile, drv) ) {
4692                 in_use = True;
4693                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4694                 fstrcpy( src->datafile, "" );
4695         }
4696                 
4697         if ( drv_file_in_use(src->configfile, drv) ) {
4698                 in_use = True;
4699                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4700                 fstrcpy( src->configfile, "" );
4701         }
4702                 
4703         if ( drv_file_in_use(src->helpfile, drv) ) {
4704                 in_use = True;
4705                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4706                 fstrcpy( src->helpfile, "" );
4707         }
4708         
4709         /* are there any dependentfiles to examine? */
4710         
4711         if ( !src->dependentfiles )
4712                 return in_use;
4713                 
4714         while ( *src->dependentfiles[i] ) {
4715                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4716                         in_use = True;
4717                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4718                         trim_dependent_file( src->dependentfiles, i );
4719                 } else
4720                         i++;
4721         }               
4722                 
4723         return in_use;
4724 }
4725
4726 /****************************************************************************
4727   Determine whether or not a particular driver files are currently being 
4728   used by any other driver.  
4729   
4730   Return value is True if any files were in use by other drivers
4731   and False otherwise.
4732   
4733   Upon return, *info has been modified to only contain the driver files
4734   which are not in use
4735 ****************************************************************************/
4736
4737 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4738 {
4739         int                             i;
4740         int                             ndrivers;
4741         uint32                          version;
4742         fstring                         *list = NULL;
4743         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
4744         
4745         if ( !info )
4746                 return False;
4747         
4748         version = info->cversion;
4749         
4750         /* loop over all driver versions */
4751         
4752         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4753         
4754         /* get the list of drivers */
4755                 
4756         list = NULL;
4757         ndrivers = get_ntdrivers(&list, info->environment, version);
4758                 
4759         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
4760                 ndrivers, info->environment, version));
4761
4762         /* check each driver for overlap in files */
4763                 
4764         for (i=0; i<ndrivers; i++) {
4765                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4766                         
4767                 ZERO_STRUCT(driver);
4768                         
4769                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4770                         SAFE_FREE(list);
4771                         return True;
4772                 }
4773                         
4774                 /* check if d2 uses any files from d1 */
4775                 /* only if this is a different driver than the one being deleted */
4776                         
4777                 if ( !strequal(info->name, driver.info_3->name) ) {
4778                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
4779                                 free_a_printer_driver(driver, 3);
4780                                 SAFE_FREE( list );
4781                                 return True;
4782                         }
4783                 }
4784         
4785                 free_a_printer_driver(driver, 3);
4786         }       
4787         
4788         SAFE_FREE(list);
4789         
4790         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4791         
4792         driver.info_3 = info;
4793         
4794         if ( DEBUGLEVEL >= 20 )
4795                 dump_a_printer_driver( driver, 3 );
4796         
4797         return False;
4798 }
4799
4800 /****************************************************************************
4801   Actually delete the driver files.  Make sure that 
4802   printer_driver_files_in_use() return False before calling 
4803   this.
4804 ****************************************************************************/
4805
4806 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4807 {
4808         int i = 0;
4809         char *s;
4810         connection_struct *conn;
4811         DATA_BLOB null_pw;
4812         NTSTATUS nt_status;
4813         fstring res_type;
4814         BOOL bad_path;
4815         SMB_STRUCT_STAT  st;
4816
4817         if ( !info_3 )
4818                 return False;
4819                 
4820         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4821         
4822         /*
4823          * Connect to the print$ share under the same account as the 
4824          * user connected to the rpc pipe. Note we must be root to 
4825          * do this.
4826          */
4827          
4828         null_pw = data_blob( NULL, 0 );
4829         fstrcpy(res_type, "A:");
4830         become_root();
4831         conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4832         unbecome_root();
4833         
4834         if ( !conn ) {
4835                 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4836                 return False;
4837         }
4838
4839         /* Save who we are - we are temporarily becoming the connection user. */
4840
4841         if ( !become_user(conn, conn->vuid) ) {
4842                 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4843                 return False;
4844         }
4845
4846         /* now delete the files; must strip the '\print$' string from 
4847            fron of path                                                */
4848         
4849         if ( *info_3->driverpath ) {
4850                 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4851                         driver_unix_convert(s, conn, NULL, &bad_path, &st);
4852                         DEBUG(10,("deleting driverfile [%s]\n", s));
4853                         unlink_internals(conn, 0, s);
4854                 }
4855         }
4856                 
4857         if ( *info_3->configfile ) {
4858                 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4859                         driver_unix_convert(s, conn, NULL, &bad_path, &st);
4860                         DEBUG(10,("deleting configfile [%s]\n", s));
4861                         unlink_internals(conn, 0, s);
4862                 }
4863         }
4864         
4865         if ( *info_3->datafile ) {
4866                 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4867                         driver_unix_convert(s, conn, NULL, &bad_path, &st);
4868                         DEBUG(10,("deleting datafile [%s]\n", s));
4869                         unlink_internals(conn, 0, s);
4870                 }
4871         }
4872         
4873         if ( *info_3->helpfile ) {
4874                 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4875                         driver_unix_convert(s, conn, NULL, &bad_path, &st);
4876                         DEBUG(10,("deleting helpfile [%s]\n", s));
4877                         unlink_internals(conn, 0, s);
4878                 }
4879         }
4880         
4881         /* check if we are done removing files */
4882         
4883         if ( info_3->dependentfiles ) {
4884                 while ( *info_3->dependentfiles[i] ) {
4885                         char *file;
4886
4887                         /* bypass the "\print$" portion of the path */
4888                         
4889                         if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4890                                 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4891                                 DEBUG(10,("deleting dependent file [%s]\n", file));
4892                                 unlink_internals(conn, 0, file );
4893                         }
4894                         
4895                         i++;
4896                 }
4897         }
4898
4899         unbecome_user();
4900         
4901         return True;
4902 }
4903
4904 /****************************************************************************
4905  Remove a printer driver from the TDB.  This assumes that the the driver was
4906  previously looked up.
4907  ***************************************************************************/
4908
4909 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4910                               uint32 version, BOOL delete_files )
4911 {
4912         pstring         key;
4913         const char     *arch;
4914         TDB_DATA        kbuf, dbuf;
4915         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
4916
4917         /* delete the tdb data first */
4918
4919         arch = get_short_archi(info_3->environment);
4920         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4921                 arch, version, info_3->name);
4922
4923         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4924                 key, delete_files ? "TRUE" : "FALSE" ));
4925
4926         ctr.info_3 = info_3;
4927         dump_a_printer_driver( ctr, 3 );
4928
4929         kbuf.dptr=key;
4930         kbuf.dsize=strlen(key)+1;
4931
4932         /* check if the driver actually exists for this environment */
4933         
4934         dbuf = tdb_fetch( tdb_drivers, kbuf );
4935         if ( !dbuf.dptr ) {
4936                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4937                 return WERR_UNKNOWN_PRINTER_DRIVER;
4938         }
4939                 
4940         SAFE_FREE( dbuf.dptr );
4941         
4942         /* ok... the driver exists so the delete should return success */
4943                 
4944         if (tdb_delete(tdb_drivers, kbuf) == -1) {
4945                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4946                 return WERR_ACCESS_DENIED;
4947         }
4948
4949         /*
4950          * now delete any associated files if delete_files == True
4951          * even if this part failes, we return succes because the
4952          * driver doesn not exist any more
4953          */
4954
4955         if ( delete_files )
4956                 delete_driver_files( info_3, user );
4957                         
4958                 
4959         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4960
4961         return WERR_OK;
4962         }
4963         
4964 /****************************************************************************
4965  Store a security desc for a printer.
4966 ****************************************************************************/
4967
4968 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
4969 {
4970         SEC_DESC_BUF *new_secdesc_ctr = NULL;
4971         SEC_DESC_BUF *old_secdesc_ctr = NULL;
4972         prs_struct ps;
4973         TALLOC_CTX *mem_ctx = NULL;
4974         fstring key;
4975         WERROR status;
4976         fstring norm_sharename;
4977
4978         fstrcpy( norm_sharename, sharename );
4979         strlower_m( norm_sharename );
4980
4981         mem_ctx = talloc_init("nt_printing_setsec");
4982         if (mem_ctx == NULL)
4983                 return WERR_NOMEM;
4984
4985         /* The old owner and group sids of the security descriptor are not
4986            present when new ACEs are added or removed by changing printer
4987            permissions through NT.  If they are NULL in the new security
4988            descriptor then copy them over from the old one. */
4989
4990         if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4991                 DOM_SID *owner_sid, *group_sid;
4992                 SEC_ACL *dacl, *sacl;
4993                 SEC_DESC *psd = NULL;
4994                 size_t size;
4995
4996                 nt_printing_getsec(mem_ctx, norm_sharename, &old_secdesc_ctr);
4997
4998                 /* Pick out correct owner and group sids */
4999
5000                 owner_sid = secdesc_ctr->sec->owner_sid ?
5001                         secdesc_ctr->sec->owner_sid :
5002                         old_secdesc_ctr->sec->owner_sid;
5003
5004                 group_sid = secdesc_ctr->sec->grp_sid ?
5005                         secdesc_ctr->sec->grp_sid :
5006                         old_secdesc_ctr->sec->grp_sid;
5007
5008                 dacl = secdesc_ctr->sec->dacl ?
5009                         secdesc_ctr->sec->dacl :
5010                         old_secdesc_ctr->sec->dacl;
5011
5012                 sacl = secdesc_ctr->sec->sacl ?
5013                         secdesc_ctr->sec->sacl :
5014                         old_secdesc_ctr->sec->sacl;
5015
5016                 /* Make a deep copy of the security descriptor */
5017
5018                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
5019                                     owner_sid, group_sid,
5020                                     sacl,
5021                                     dacl,
5022                                     &size);
5023
5024                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5025         }
5026
5027         if (!new_secdesc_ctr) {
5028                 new_secdesc_ctr = secdesc_ctr;
5029         }
5030
5031         /* Store the security descriptor in a tdb */
5032
5033         prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
5034                  sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
5035
5036         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
5037                              &ps, 1)) {
5038                 status = WERR_BADFUNC;
5039                 goto out;
5040         }
5041
5042         slprintf(key, sizeof(key)-1, "SECDESC/%s", norm_sharename);
5043
5044         if (tdb_prs_store(tdb_printers, key, &ps)==0) {
5045                 status = WERR_OK;
5046         } else {
5047                 DEBUG(1,("Failed to store secdesc for %s\n", norm_sharename));
5048                 status = WERR_BADFUNC;
5049         }
5050
5051         /* Free malloc'ed memory */
5052
5053  out:
5054
5055         prs_mem_free(&ps);
5056         if (mem_ctx)
5057                 talloc_destroy(mem_ctx);
5058         return status;
5059 }
5060
5061 /****************************************************************************
5062  Construct a default security descriptor buffer for a printer.
5063 ****************************************************************************/
5064
5065 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5066 {
5067         SEC_ACE ace[5]; /* max number of ace entries */
5068         int i = 0;
5069         SEC_ACCESS sa;
5070         SEC_ACL *psa = NULL;
5071         SEC_DESC_BUF *sdb = NULL;
5072         SEC_DESC *psd = NULL;
5073         DOM_SID adm_sid;
5074         size_t sd_size;
5075
5076         /* Create an ACE where Everyone is allowed to print */
5077
5078         init_sec_access(&sa, PRINTER_ACE_PRINT);
5079         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5080                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5081
5082         /* Add the domain admins group if we are a DC */
5083         
5084         if ( IS_DC ) {
5085                 DOM_SID domadmins_sid;
5086                 
5087                 sid_copy(&domadmins_sid, get_global_sam_sid());
5088                 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5089                 
5090                 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5091                 init_sec_ace(&ace[i++], &domadmins_sid, 
5092                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5093                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5094                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5095                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5096         }
5097         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5098                 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5099
5100                 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5101                 init_sec_ace(&ace[i++], &adm_sid, 
5102                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5103                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5104                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5105                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5106         }
5107
5108         /* add BUILTIN\Administrators as FULL CONTROL */
5109
5110         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5111         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 
5112                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5113                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5114         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 
5115                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5116                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5117
5118         /* Make the security descriptor owned by the BUILTIN\Administrators */
5119
5120         /* The ACL revision number in rpc_secdesc.h differs from the one
5121            created by NT when setting ACE entries in printer
5122            descriptors.  NT4 complains about the property being edited by a
5123            NT5 machine. */
5124
5125         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5126                 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5127                         &global_sid_Builtin_Administrators, 
5128                         &global_sid_Builtin_Administrators,
5129                         NULL, psa, &sd_size);
5130         }
5131
5132         if (!psd) {
5133                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5134                 return NULL;
5135         }
5136
5137         sdb = make_sec_desc_buf(ctx, sd_size, psd);
5138
5139         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5140                  (unsigned int)sd_size));
5141
5142         return sdb;
5143 }
5144
5145 /****************************************************************************
5146  Get a security desc for a printer.
5147 ****************************************************************************/
5148
5149 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5150 {
5151         prs_struct ps;
5152         fstring key;
5153         char *temp;
5154         fstring norm_sharename;
5155
5156         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5157                 sharename = temp + 1;
5158         }
5159
5160         /* Fetch security descriptor from tdb */
5161
5162         fstrcpy( norm_sharename, sharename );
5163         strlower_m( norm_sharename );
5164
5165         slprintf(key, sizeof(key)-1, "SECDESC/%s", norm_sharename);
5166
5167         if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
5168             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5169
5170                 DEBUG(4,("using default secdesc for %s\n", norm_sharename));
5171
5172                 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5173                         return False;
5174                 }
5175
5176                 /* Save default security descriptor for later */
5177
5178                 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
5179                                 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5180
5181                 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
5182                         tdb_prs_store(tdb_printers, key, &ps);
5183
5184                 prs_mem_free(&ps);
5185
5186                 return True;
5187         }
5188
5189         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5190            this security descriptor has been created when winbindd was
5191            down.  Take ownership of security descriptor. */
5192
5193         if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
5194                 DOM_SID owner_sid;
5195
5196                 /* Change sd owner to workgroup administrator */
5197
5198                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5199                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5200                         SEC_DESC *psd = NULL;
5201                         size_t size;
5202
5203                         /* Create new sd */
5204
5205                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5206
5207                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
5208                                             &owner_sid,
5209                                             (*secdesc_ctr)->sec->grp_sid,
5210                                             (*secdesc_ctr)->sec->sacl,
5211                                             (*secdesc_ctr)->sec->dacl,
5212                                             &size);
5213
5214                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5215
5216                         /* Swap with other one */
5217
5218                         *secdesc_ctr = new_secdesc_ctr;
5219
5220                         /* Set it */
5221
5222                         nt_printing_setsec(norm_sharename, *secdesc_ctr);
5223                 }
5224         }
5225
5226         if (DEBUGLEVEL >= 10) {
5227                 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
5228                 int i;
5229
5230                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
5231                            norm_sharename, the_acl->num_aces));
5232
5233                 for (i = 0; i < the_acl->num_aces; i++) {
5234                         fstring sid_str;
5235
5236                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
5237
5238                         DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5239                                    the_acl->ace[i].type, the_acl->ace[i].flags, 
5240                                    the_acl->ace[i].info.mask)); 
5241                 }
5242         }
5243
5244         prs_mem_free(&ps);
5245         return True;
5246 }
5247
5248 /* error code:
5249         0: everything OK
5250         1: level not implemented
5251         2: file doesn't exist
5252         3: can't allocate memory
5253         4: can't free memory
5254         5: non existant struct
5255 */
5256
5257 /*
5258         A printer and a printer driver are 2 different things.
5259         NT manages them separatelly, Samba does the same.
5260         Why ? Simply because it's easier and it makes sense !
5261         
5262         Now explanation: You have 3 printers behind your samba server,
5263         2 of them are the same make and model (laser A and B). But laser B
5264         has an 3000 sheet feeder and laser A doesn't such an option.
5265         Your third printer is an old dot-matrix model for the accounting :-).
5266         
5267         If the /usr/local/samba/lib directory (default dir), you will have
5268         5 files to describe all of this.
5269         
5270         3 files for the printers (1 by printer):
5271                 NTprinter_laser A
5272                 NTprinter_laser B
5273                 NTprinter_accounting
5274         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5275                 NTdriver_printer model X
5276                 NTdriver_printer model Y
5277
5278 jfm: I should use this comment for the text file to explain
5279         same thing for the forms BTW.
5280         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5281
5282 */
5283
5284 /* Convert generic access rights to printer object specific access rights.
5285    It turns out that NT4 security descriptors use generic access rights and
5286    NT5 the object specific ones. */
5287
5288 void map_printer_permissions(SEC_DESC *sd)
5289 {
5290         int i;
5291
5292         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5293                 se_map_generic(&sd->dacl->ace[i].info.mask,
5294                                &printer_generic_mapping);
5295         }
5296 }
5297
5298 /****************************************************************************
5299  Check a user has permissions to perform the given operation.  We use the
5300  permission constants defined in include/rpc_spoolss.h to check the various
5301  actions we perform when checking printer access.
5302
5303    PRINTER_ACCESS_ADMINISTER:
5304        print_queue_pause, print_queue_resume, update_printer_sec,
5305        update_printer, spoolss_addprinterex_level_2,
5306        _spoolss_setprinterdata
5307
5308    PRINTER_ACCESS_USE:
5309        print_job_start
5310
5311    JOB_ACCESS_ADMINISTER:
5312        print_job_delete, print_job_pause, print_job_resume,
5313        print_queue_purge
5314
5315   Try access control in the following order (for performance reasons):
5316     1)  root ans SE_PRINT_OPERATOR can do anything (easy check) 
5317     2)  check security descriptor (bit comparisons in memory)
5318     3)  "printer admins" (may result in numerous calls to winbind)
5319
5320  ****************************************************************************/
5321 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5322 {
5323         SEC_DESC_BUF *secdesc = NULL;
5324         uint32 access_granted;
5325         NTSTATUS status;
5326         BOOL result;
5327         const char *pname;
5328         TALLOC_CTX *mem_ctx = NULL;
5329         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5330         
5331         /* If user is NULL then use the current_user structure */
5332
5333         if (!user)
5334                 user = &current_user;
5335
5336         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5337
5338         if ( user->uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5339                 return True;
5340         }
5341
5342         /* Get printer name */
5343
5344         pname = PRINTERNAME(snum);
5345
5346         if (!pname || !*pname) {
5347                 errno = EACCES;
5348                 return False;
5349         }
5350
5351         /* Get printer security descriptor */
5352
5353         if(!(mem_ctx = talloc_init("print_access_check"))) {
5354                 errno = ENOMEM;
5355                 return False;
5356         }
5357
5358         nt_printing_getsec(mem_ctx, pname, &secdesc);
5359
5360         if (access_type == JOB_ACCESS_ADMINISTER) {
5361                 SEC_DESC_BUF *parent_secdesc = secdesc;
5362
5363                 /* Create a child security descriptor to check permissions
5364                    against.  This is because print jobs are child objects
5365                    objects of a printer. */
5366
5367                 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5368
5369                 /* Now this is the bit that really confuses me.  The access
5370                    type needs to be changed from JOB_ACCESS_ADMINISTER to
5371                    PRINTER_ACCESS_ADMINISTER for this to work.  Something
5372                    to do with the child (job) object becoming like a
5373                    printer??  -tpot */
5374
5375                 access_type = PRINTER_ACCESS_ADMINISTER;
5376         }
5377         
5378         /* Check access */
5379         
5380         map_printer_permissions(secdesc->sec);
5381
5382         result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5383                                  &access_granted, &status);
5384
5385         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5386
5387         /* see if we need to try the printer admin list */
5388
5389         if ( access_granted == 0 ) {
5390                 if ( user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups) )
5391                         return True;
5392         }
5393
5394         talloc_destroy(mem_ctx);
5395         
5396         if (!result)
5397                 errno = EACCES;
5398
5399         return result;
5400 }
5401
5402 /****************************************************************************
5403  Check the time parameters allow a print operation.
5404 *****************************************************************************/
5405
5406 BOOL print_time_access_check(int snum)
5407 {
5408         NT_PRINTER_INFO_LEVEL *printer = NULL;
5409         BOOL ok = False;
5410         time_t now = time(NULL);
5411         struct tm *t;
5412         uint32 mins;
5413
5414         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5415                 return False;
5416
5417         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5418                 ok = True;
5419
5420         t = gmtime(&now);
5421         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5422
5423         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5424                 ok = True;
5425
5426         free_a_printer(&printer, 2);
5427
5428         if (!ok)
5429                 errno = EACCES;
5430
5431         return ok;
5432 }
5433
5434 /****************************************************************************
5435  Fill in the servername sent in the _spoolss_open_printer_ex() call
5436 ****************************************************************************/
5437 char* get_server_name( Printer_entry *printer )
5438 {
5439         return printer->servername;
5440 }