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