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