r25009: Large patch discussed with Volker. Move unix_convert to a talloc-based
[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 GENERIC_MAPPING printer_generic_mapping = {
46         PRINTER_READ,
47         PRINTER_WRITE,
48         PRINTER_EXECUTE,
49         PRINTER_ALL_ACCESS
50 };
51
52 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 GENERIC_MAPPING printserver_generic_mapping = {
62         SERVER_READ,
63         SERVER_WRITE,
64         SERVER_EXECUTE,
65         SERVER_ALL_ACCESS
66 };
67
68 STANDARD_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(lock_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                         lock_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(lock_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                         lock_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(lock_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                         lock_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(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)-1);
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)-1);
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)-1);
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)-1);
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)-1);
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
1750         memset(inbuf, '\0', sizeof(inbuf));
1751         memset(outbuf, '\0', sizeof(outbuf));
1752         *perr = WERR_OK;
1753
1754         if (level==3)
1755                 driver=driver_abstract.info_3;
1756         else if (level==6) {
1757                 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1758                 driver = &converted_driver;
1759         } else {
1760                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1761                 return WERR_UNKNOWN_LEVEL;
1762         }
1763
1764         architecture = get_short_archi(driver->environment);
1765         if (!architecture) {
1766                 return WERR_UNKNOWN_PRINTER_DRIVER;
1767         }
1768
1769         /*
1770          * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1771          * Note we must be root to do this.
1772          */
1773
1774         null_pw = data_blob_null;
1775         fstrcpy(res_type, "A:");
1776         become_root();
1777         conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1778         unbecome_root();
1779
1780         if (conn == NULL) {
1781                 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1782                 *perr = ntstatus_to_werror(nt_status);
1783                 return WERR_NO_SUCH_SHARE;
1784         }
1785
1786         /*
1787          * Save who we are - we are temporarily becoming the connection user.
1788          */
1789
1790         if (!become_user(conn, conn->vuid)) {
1791                 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1792                 return WERR_ACCESS_DENIED;
1793         }
1794
1795         /*
1796          * make the directories version and version\driver_name
1797          * under the architecture directory.
1798          */
1799         DEBUG(5,("Creating first directory\n"));
1800         slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1801         driver_unix_convert(conn,new_dir,&st);
1802         create_directory(conn, new_dir);
1803
1804         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1805          * listed for this driver which has already been moved, skip it (note:
1806          * drivers may list the same file name several times. Then check if the
1807          * file already exists in archi\cversion\, if so, check that the version
1808          * info (or time stamps if version info is unavailable) is newer (or the
1809          * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1810          * Otherwise, delete the file.
1811          *
1812          * If a file is not moved to archi\cversion\ because of an error, all the
1813          * rest of the 'unmoved' driver files are removed from archi\. If one or
1814          * more of the driver's files was already moved to archi\cversion\, it
1815          * potentially leaves the driver in a partially updated state. Version
1816          * trauma will most likely occur if an client attempts to use any printer
1817          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1818          * done is appropriate... later JRR
1819          */
1820
1821         DEBUG(5,("Moving files now !\n"));
1822
1823         if (driver->driverpath && strlen(driver->driverpath)) {
1824                 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);      
1825                 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);   
1826                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1827                         driver_unix_convert(conn,new_name,&st);
1828                         if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1829                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1830                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1831                                                 new_name, old_name));
1832                                 *perr = WERR_ACCESS_DENIED;
1833                                 ver = -1;
1834                         }
1835                 } 
1836         }
1837
1838         if (driver->datafile && strlen(driver->datafile)) {
1839                 if (!strequal(driver->datafile, driver->driverpath)) {
1840                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);        
1841                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);     
1842                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1843                                 driver_unix_convert(conn,new_name,&st);
1844                                 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1845                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1846                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1847                                                         new_name, old_name));
1848                                         *perr = WERR_ACCESS_DENIED;
1849                                         ver = -1;
1850                                 }
1851                         }
1852                 }
1853         }
1854
1855         if (driver->configfile && strlen(driver->configfile)) {
1856                 if (!strequal(driver->configfile, driver->driverpath) &&
1857                         !strequal(driver->configfile, driver->datafile)) {
1858                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);      
1859                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);   
1860                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1861                                 driver_unix_convert(conn,new_name,&st);
1862                                 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1863                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1864                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1865                                                         new_name, old_name));
1866                                         *perr = WERR_ACCESS_DENIED;
1867                                         ver = -1;
1868                                 }
1869                         }
1870                 }
1871         }
1872
1873         if (driver->helpfile && strlen(driver->helpfile)) {
1874                 if (!strequal(driver->helpfile, driver->driverpath) &&
1875                         !strequal(driver->helpfile, driver->datafile) &&
1876                         !strequal(driver->helpfile, driver->configfile)) {
1877                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);        
1878                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);     
1879                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1880                                 driver_unix_convert(conn,new_name,&st);
1881                                 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1882                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1883                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1884                                                         new_name, old_name));
1885                                         *perr = WERR_ACCESS_DENIED;
1886                                         ver = -1;
1887                                 }
1888                         }
1889                 }
1890         }
1891
1892         if (driver->dependentfiles) {
1893                 for (i=0; *driver->dependentfiles[i]; i++) {
1894                         if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1895                                 !strequal(driver->dependentfiles[i], driver->datafile) &&
1896                                 !strequal(driver->dependentfiles[i], driver->configfile) &&
1897                                 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1898                                 int j;
1899                                 for (j=0; j < i; j++) {
1900                                         if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1901                                                 goto NextDriver;
1902                                         }
1903                                 }
1904
1905                                 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);       
1906                                 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);    
1907                                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1908                                         driver_unix_convert(conn,new_name,&st);
1909                                         if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name,
1910                                                         OPENX_FILE_EXISTS_TRUNCATE|
1911                                                         OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1912                                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1913                                                                 new_name, old_name));
1914                                                 *perr = WERR_ACCESS_DENIED;
1915                                                 ver = -1;
1916                                         }
1917                                 }
1918                         }
1919                 NextDriver: ;
1920                 }
1921         }
1922
1923         close_cnum(conn, user->vuid);
1924         unbecome_user();
1925
1926         return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
1927 }
1928
1929 /****************************************************************************
1930 ****************************************************************************/
1931 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1932 {
1933         int len, buflen;
1934         const char *architecture;
1935         pstring directory;
1936         fstring temp_name;
1937         pstring key;
1938         uint8 *buf;
1939         int i, ret;
1940         TDB_DATA dbuf;
1941
1942         architecture = get_short_archi(driver->environment);
1943         if (!architecture) {
1944                 return (uint32)-1;
1945         }
1946
1947         /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1948          * \\server is added in the rpc server layer.
1949          * It does make sense to NOT store the server's name in the printer TDB.
1950          */
1951
1952         slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1953
1954         /* .inf files do not always list a file for each of the four standard files. 
1955          * Don't prepend a path to a null filename, or client claims:
1956          *   "The server on which the printer resides does not have a suitable 
1957          *   <printer driver name> printer driver installed. Click OK if you 
1958          *   wish to install the driver on your local machine."
1959          */
1960         if (strlen(driver->driverpath)) {
1961                 fstrcpy(temp_name, driver->driverpath);
1962                 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1963         }
1964
1965         if (strlen(driver->datafile)) {
1966                 fstrcpy(temp_name, driver->datafile);
1967                 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1968         }
1969
1970         if (strlen(driver->configfile)) {
1971                 fstrcpy(temp_name, driver->configfile);
1972                 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1973         }
1974
1975         if (strlen(driver->helpfile)) {
1976                 fstrcpy(temp_name, driver->helpfile);
1977                 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1978         }
1979
1980         if (driver->dependentfiles) {
1981                 for (i=0; *driver->dependentfiles[i]; i++) {
1982                         fstrcpy(temp_name, driver->dependentfiles[i]);
1983                         slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1984                 }
1985         }
1986
1987         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1988
1989         DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1990
1991         buf = NULL;
1992         len = buflen = 0;
1993
1994  again:
1995         len = 0;
1996         len += tdb_pack(buf+len, buflen-len, "dffffffff",
1997                         driver->cversion,
1998                         driver->name,
1999                         driver->environment,
2000                         driver->driverpath,
2001                         driver->datafile,
2002                         driver->configfile,
2003                         driver->helpfile,
2004                         driver->monitorname,
2005                         driver->defaultdatatype);
2006
2007         if (driver->dependentfiles) {
2008                 for (i=0; *driver->dependentfiles[i]; i++) {
2009                         len += tdb_pack(buf+len, buflen-len, "f",
2010                                         driver->dependentfiles[i]);
2011                 }
2012         }
2013
2014         if (len != buflen) {
2015                 buf = (uint8 *)SMB_REALLOC(buf, len);
2016                 if (!buf) {
2017                         DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2018                         ret = -1;
2019                         goto done;
2020                 }
2021                 buflen = len;
2022                 goto again;
2023         }
2024
2025         dbuf.dptr = buf;
2026         dbuf.dsize = len;
2027         
2028         ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2029
2030 done:
2031         if (ret)
2032                 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2033
2034         SAFE_FREE(buf);
2035         return ret;
2036 }
2037
2038 /****************************************************************************
2039 ****************************************************************************/
2040 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2041 {
2042         NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2043
2044         ZERO_STRUCT(info3);
2045         info3.cversion = driver->version;
2046         fstrcpy(info3.name,driver->name);
2047         fstrcpy(info3.environment,driver->environment);
2048         fstrcpy(info3.driverpath,driver->driverpath);
2049         fstrcpy(info3.datafile,driver->datafile);
2050         fstrcpy(info3.configfile,driver->configfile);
2051         fstrcpy(info3.helpfile,driver->helpfile);
2052         fstrcpy(info3.monitorname,driver->monitorname);
2053         fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2054         info3.dependentfiles = driver->dependentfiles;
2055
2056         return add_a_printer_driver_3(&info3);
2057 }
2058
2059
2060 /****************************************************************************
2061 ****************************************************************************/
2062 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2063 {
2064         NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2065
2066         ZERO_STRUCT(info);
2067
2068         fstrcpy(info.name, driver);
2069         fstrcpy(info.defaultdatatype, "RAW");
2070         
2071         fstrcpy(info.driverpath, "");
2072         fstrcpy(info.datafile, "");
2073         fstrcpy(info.configfile, "");
2074         fstrcpy(info.helpfile, "");
2075
2076         if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2077                 return WERR_NOMEM;
2078
2079         memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2080         fstrcpy(info.dependentfiles[0], "");
2081
2082         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
2083         if (!*info_ptr) {
2084                 SAFE_FREE(info.dependentfiles);
2085                 return WERR_NOMEM;
2086         }
2087         
2088         return WERR_OK;
2089 }
2090
2091 /****************************************************************************
2092 ****************************************************************************/
2093 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
2094 {
2095         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2096         TDB_DATA dbuf;
2097         const char *architecture;
2098         int len = 0;
2099         int i;
2100         pstring key;
2101
2102         ZERO_STRUCT(driver);
2103
2104         architecture = get_short_archi(arch);
2105         if ( !architecture ) {
2106                 return WERR_UNKNOWN_PRINTER_DRIVER;
2107         }
2108         
2109         /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2110         
2111         if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2112                 version = 0;
2113
2114         DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2115
2116         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
2117         
2118         dbuf = tdb_fetch_bystring(tdb_drivers, key);
2119         if (!dbuf.dptr) 
2120                 return WERR_UNKNOWN_PRINTER_DRIVER;
2121
2122         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2123                           &driver.cversion,
2124                           driver.name,
2125                           driver.environment,
2126                           driver.driverpath,
2127                           driver.datafile,
2128                           driver.configfile,
2129                           driver.helpfile,
2130                           driver.monitorname,
2131                           driver.defaultdatatype);
2132
2133         i=0;
2134         while (len < dbuf.dsize) {
2135                 driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2136                 if ( !driver.dependentfiles ) {
2137                         DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2138                         break;
2139                 }
2140
2141                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2142                                   &driver.dependentfiles[i]);
2143                 i++;
2144         }
2145         
2146         if ( driver.dependentfiles )
2147                 fstrcpy( driver.dependentfiles[i], "" );
2148
2149         SAFE_FREE(dbuf.dptr);
2150
2151         if (len != dbuf.dsize) {
2152                 SAFE_FREE(driver.dependentfiles);
2153
2154                 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2155         }
2156
2157         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2158         if (!*info_ptr) {
2159                 SAFE_FREE(driver.dependentfiles);
2160                 return WERR_NOMEM;
2161         }
2162
2163         return WERR_OK;
2164 }
2165
2166 /****************************************************************************
2167  Debugging function, dump at level 6 the struct in the logs.
2168 ****************************************************************************/
2169
2170 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2171 {
2172         uint32 result;
2173         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2174         int i;
2175         
2176         DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2177         
2178         switch (level)
2179         {
2180                 case 3:
2181                 {
2182                         if (driver.info_3 == NULL)
2183                                 result=5;
2184                         else {
2185                                 info3=driver.info_3;
2186                         
2187                                 DEBUGADD(20,("version:[%d]\n",         info3->cversion));
2188                                 DEBUGADD(20,("name:[%s]\n",            info3->name));
2189                                 DEBUGADD(20,("environment:[%s]\n",     info3->environment));
2190                                 DEBUGADD(20,("driverpath:[%s]\n",      info3->driverpath));
2191                                 DEBUGADD(20,("datafile:[%s]\n",        info3->datafile));
2192                                 DEBUGADD(20,("configfile:[%s]\n",      info3->configfile));
2193                                 DEBUGADD(20,("helpfile:[%s]\n",        info3->helpfile));
2194                                 DEBUGADD(20,("monitorname:[%s]\n",     info3->monitorname));
2195                                 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2196                                 
2197                                 for (i=0; info3->dependentfiles &&
2198                                           *info3->dependentfiles[i]; i++) {
2199                                         DEBUGADD(20,("dependentfile:[%s]\n",
2200                                                       info3->dependentfiles[i]));
2201                                 }
2202                                 result=0;
2203                         }
2204                         break;
2205                 }
2206                 default:
2207                         DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2208                         result=1;
2209                         break;
2210         }
2211         
2212         return result;
2213 }
2214
2215 /****************************************************************************
2216 ****************************************************************************/
2217 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2218 {
2219         int len = 0;
2220
2221         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2222
2223         if (!nt_devmode)
2224                 return len;
2225
2226         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2227                         nt_devmode->devicename,
2228                         nt_devmode->formname,
2229
2230                         nt_devmode->specversion,
2231                         nt_devmode->driverversion,
2232                         nt_devmode->size,
2233                         nt_devmode->driverextra,
2234                         nt_devmode->orientation,
2235                         nt_devmode->papersize,
2236                         nt_devmode->paperlength,
2237                         nt_devmode->paperwidth,
2238                         nt_devmode->scale,
2239                         nt_devmode->copies,
2240                         nt_devmode->defaultsource,
2241                         nt_devmode->printquality,
2242                         nt_devmode->color,
2243                         nt_devmode->duplex,
2244                         nt_devmode->yresolution,
2245                         nt_devmode->ttoption,
2246                         nt_devmode->collate,
2247                         nt_devmode->logpixels,
2248                         
2249                         nt_devmode->fields,
2250                         nt_devmode->bitsperpel,
2251                         nt_devmode->pelswidth,
2252                         nt_devmode->pelsheight,
2253                         nt_devmode->displayflags,
2254                         nt_devmode->displayfrequency,
2255                         nt_devmode->icmmethod,
2256                         nt_devmode->icmintent,
2257                         nt_devmode->mediatype,
2258                         nt_devmode->dithertype,
2259                         nt_devmode->reserved1,
2260                         nt_devmode->reserved2,
2261                         nt_devmode->panningwidth,
2262                         nt_devmode->panningheight,
2263                         nt_devmode->nt_dev_private);
2264
2265         
2266         if (nt_devmode->nt_dev_private) {
2267                 len += tdb_pack(buf+len, buflen-len, "B",
2268                                 nt_devmode->driverextra,
2269                                 nt_devmode->nt_dev_private);
2270         }
2271
2272         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2273
2274         return len;
2275 }
2276
2277 /****************************************************************************
2278  Pack all values in all printer keys
2279  ***************************************************************************/
2280  
2281 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2282 {
2283         int             len = 0;
2284         int             i, j;
2285         REGISTRY_VALUE  *val;
2286         REGVAL_CTR      *val_ctr;
2287         pstring         path;
2288         int             num_values;
2289
2290         if ( !data )
2291                 return 0;
2292
2293         /* loop over all keys */
2294                 
2295         for ( i=0; i<data->num_keys; i++ ) {    
2296                 val_ctr = data->keys[i].values;
2297                 num_values = regval_ctr_numvals( val_ctr );
2298
2299                 /* pack the keyname followed by a empty value */
2300
2301                 len += tdb_pack(buf+len, buflen-len, "pPdB", 
2302                                 &data->keys[i].name,
2303                                 data->keys[i].name, 
2304                                 REG_NONE,
2305                                 0,
2306                                 NULL);
2307                 
2308                 /* now loop over all values */
2309                 
2310                 for ( j=0; j<num_values; j++ ) {
2311                         /* pathname should be stored as <key>\<value> */
2312                         
2313                         val = regval_ctr_specific_value( val_ctr, j );
2314                         pstrcpy( path, data->keys[i].name );
2315                         pstrcat( path, "\\" );
2316                         pstrcat( path, regval_name(val) );
2317                         
2318                         len += tdb_pack(buf+len, buflen-len, "pPdB",
2319                                         val,
2320                                         path,
2321                                         regval_type(val),
2322                                         regval_size(val),
2323                                         regval_data_p(val) );
2324
2325                         DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2326                 }
2327         
2328         }
2329
2330         /* terminator */
2331         
2332         len += tdb_pack(buf+len, buflen-len, "p", NULL);
2333
2334         return len;
2335 }
2336
2337
2338 /****************************************************************************
2339  Delete a printer - this just deletes the printer info file, any open
2340  handles are not affected.
2341 ****************************************************************************/
2342
2343 uint32 del_a_printer(const char *sharename)
2344 {
2345         TDB_DATA kbuf;
2346         pstring printdb_path;
2347
2348         kbuf = make_printer_tdbkey( sharename );
2349         tdb_delete(tdb_printers, kbuf);
2350
2351         kbuf= make_printers_secdesc_tdbkey( sharename );
2352         tdb_delete(tdb_printers, kbuf);
2353
2354         close_all_print_db();
2355
2356         if (geteuid() == 0) {
2357                 pstrcpy(printdb_path, lock_path("printing/"));
2358                 pstrcat(printdb_path, sharename);
2359                 pstrcat(printdb_path, ".tdb");
2360
2361                 unlink(printdb_path);
2362         }
2363
2364         return 0;
2365 }
2366
2367 /****************************************************************************
2368 ****************************************************************************/
2369 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2370 {
2371         uint8 *buf;
2372         int buflen, len;
2373         WERROR ret;
2374         TDB_DATA kbuf, dbuf;
2375         
2376         /*
2377          * in addprinter: no servername and the printer is the name
2378          * in setprinter: servername is \\server
2379          *                and printer is \\server\\printer
2380          *
2381          * Samba manages only local printers.
2382          * we currently don't support things like i
2383          * path=\\other_server\printer
2384          *
2385          * We only store the printername, not \\server\printername
2386          */
2387
2388         if ( info->servername[0] != '\0' ) {
2389                 trim_string(info->printername, info->servername, NULL);
2390                 trim_char(info->printername, '\\', '\0');
2391                 info->servername[0]='\0';
2392         }
2393
2394         /*
2395          * JFM: one day I'll forget.
2396          * below that's info->portname because that's the SAMBA sharename
2397          * and I made NT 'thinks' it's the portname
2398          * the info->sharename is the thing you can name when you add a printer
2399          * that's the short-name when you create shared printer for 95/98
2400          * So I've made a limitation in SAMBA: you can only have 1 printer model
2401          * behind a SAMBA share.
2402          */
2403
2404         buf = NULL;
2405         buflen = 0;
2406
2407  again: 
2408         len = 0;
2409         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2410                         info->attributes,
2411                         info->priority,
2412                         info->default_priority,
2413                         info->starttime,
2414                         info->untiltime,
2415                         info->status,
2416                         info->cjobs,
2417                         info->averageppm,
2418                         info->changeid,
2419                         info->c_setprinter,
2420                         info->setuptime,
2421                         info->servername,
2422                         info->printername,
2423                         info->sharename,
2424                         info->portname,
2425                         info->drivername,
2426                         info->comment,
2427                         info->location,
2428                         info->sepfile,
2429                         info->printprocessor,
2430                         info->datatype,
2431                         info->parameters);
2432
2433         len += pack_devicemode(info->devmode, buf+len, buflen-len);
2434         
2435         len += pack_values( info->data, buf+len, buflen-len );
2436
2437         if (buflen != len) {
2438                 buf = (uint8 *)SMB_REALLOC(buf, len);
2439                 if (!buf) {
2440                         DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2441                         ret = WERR_NOMEM;
2442                         goto done;
2443                 }
2444                 buflen = len;
2445                 goto again;
2446         }
2447         
2448
2449         kbuf = make_printer_tdbkey( info->sharename );
2450
2451         dbuf.dptr = buf;
2452         dbuf.dsize = len;
2453
2454         ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2455
2456 done:
2457         if (!W_ERROR_IS_OK(ret))
2458                 DEBUG(8, ("error updating printer to tdb on disk\n"));
2459
2460         SAFE_FREE(buf);
2461
2462         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2463                  info->sharename, info->drivername, info->portname, len));
2464
2465         return ret;
2466 }
2467
2468
2469 /****************************************************************************
2470  Malloc and return an NT devicemode.
2471 ****************************************************************************/
2472
2473 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2474 {
2475
2476         char adevice[MAXDEVICENAME];
2477         NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2478
2479         if (nt_devmode == NULL) {
2480                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2481                 return NULL;
2482         }
2483
2484         ZERO_STRUCTP(nt_devmode);
2485
2486         slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2487         fstrcpy(nt_devmode->devicename, adevice);       
2488         
2489         fstrcpy(nt_devmode->formname, "Letter");
2490
2491         nt_devmode->specversion      = 0x0401;
2492         nt_devmode->driverversion    = 0x0400;
2493         nt_devmode->size             = 0x00DC;
2494         nt_devmode->driverextra      = 0x0000;
2495         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY |
2496                                        DEFAULTSOURCE | COPIES | SCALE |
2497                                        PAPERSIZE | ORIENTATION;
2498         nt_devmode->orientation      = 1;
2499         nt_devmode->papersize        = PAPER_LETTER;
2500         nt_devmode->paperlength      = 0;
2501         nt_devmode->paperwidth       = 0;
2502         nt_devmode->scale            = 0x64;
2503         nt_devmode->copies           = 1;
2504         nt_devmode->defaultsource    = BIN_FORMSOURCE;
2505         nt_devmode->printquality     = RES_HIGH;           /* 0x0258 */
2506         nt_devmode->color            = COLOR_MONOCHROME;
2507         nt_devmode->duplex           = DUP_SIMPLEX;
2508         nt_devmode->yresolution      = 0;
2509         nt_devmode->ttoption         = TT_SUBDEV;
2510         nt_devmode->collate          = COLLATE_FALSE;
2511         nt_devmode->icmmethod        = 0;
2512         nt_devmode->icmintent        = 0;
2513         nt_devmode->mediatype        = 0;
2514         nt_devmode->dithertype       = 0;
2515
2516         /* non utilisés par un driver d'imprimante */
2517         nt_devmode->logpixels        = 0;
2518         nt_devmode->bitsperpel       = 0;
2519         nt_devmode->pelswidth        = 0;
2520         nt_devmode->pelsheight       = 0;
2521         nt_devmode->displayflags     = 0;
2522         nt_devmode->displayfrequency = 0;
2523         nt_devmode->reserved1        = 0;
2524         nt_devmode->reserved2        = 0;
2525         nt_devmode->panningwidth     = 0;
2526         nt_devmode->panningheight    = 0;
2527         
2528         nt_devmode->nt_dev_private = NULL;
2529         return nt_devmode;
2530 }
2531
2532 /****************************************************************************
2533  Deepcopy an NT devicemode.
2534 ****************************************************************************/
2535
2536 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2537 {
2538         NT_DEVICEMODE *new_nt_devicemode = NULL;
2539
2540         if ( !nt_devicemode )
2541                 return NULL;
2542
2543         if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2544                 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2545                 return NULL;
2546         }
2547
2548         new_nt_devicemode->nt_dev_private = NULL;
2549         if (nt_devicemode->nt_dev_private != NULL) {
2550                 if ((new_nt_devicemode->nt_dev_private = (uint8 *)memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2551                         SAFE_FREE(new_nt_devicemode);
2552                         DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2553                         return NULL;
2554         }
2555         }
2556
2557         return new_nt_devicemode;
2558 }
2559
2560 /****************************************************************************
2561  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2562 ****************************************************************************/
2563
2564 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2565 {
2566         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2567
2568         if(nt_devmode == NULL)
2569                 return;
2570
2571         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2572
2573         SAFE_FREE(nt_devmode->nt_dev_private);
2574         SAFE_FREE(*devmode_ptr);
2575 }
2576
2577 /****************************************************************************
2578  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2579 ****************************************************************************/
2580
2581 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2582 {
2583         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2584
2585         if ( !info )
2586                 return;
2587
2588         free_nt_devicemode(&info->devmode);
2589
2590         TALLOC_FREE( *info_ptr );
2591 }
2592
2593
2594 /****************************************************************************
2595 ****************************************************************************/
2596 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2597 {
2598         int len = 0;
2599         int extra_len = 0;
2600         NT_DEVICEMODE devmode;
2601         
2602         ZERO_STRUCT(devmode);
2603
2604         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2605
2606         if (!*nt_devmode) return len;
2607
2608         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2609                           devmode.devicename,
2610                           devmode.formname,
2611
2612                           &devmode.specversion,
2613                           &devmode.driverversion,
2614                           &devmode.size,
2615                           &devmode.driverextra,
2616                           &devmode.orientation,
2617                           &devmode.papersize,
2618                           &devmode.paperlength,
2619                           &devmode.paperwidth,
2620                           &devmode.scale,
2621                           &devmode.copies,
2622                           &devmode.defaultsource,
2623                           &devmode.printquality,
2624                           &devmode.color,
2625                           &devmode.duplex,
2626                           &devmode.yresolution,
2627                           &devmode.ttoption,
2628                           &devmode.collate,
2629                           &devmode.logpixels,
2630                         
2631                           &devmode.fields,
2632                           &devmode.bitsperpel,
2633                           &devmode.pelswidth,
2634                           &devmode.pelsheight,
2635                           &devmode.displayflags,
2636                           &devmode.displayfrequency,
2637                           &devmode.icmmethod,
2638                           &devmode.icmintent,
2639                           &devmode.mediatype,
2640                           &devmode.dithertype,
2641                           &devmode.reserved1,
2642                           &devmode.reserved2,
2643                           &devmode.panningwidth,
2644                           &devmode.panningheight,
2645                           &devmode.nt_dev_private);
2646         
2647         if (devmode.nt_dev_private) {
2648                 /* the len in tdb_unpack is an int value and
2649                  * devmode.driverextra is only a short
2650                  */
2651                 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2652                 devmode.driverextra=(uint16)extra_len;
2653                 
2654                 /* check to catch an invalid TDB entry so we don't segfault */
2655                 if (devmode.driverextra == 0) {
2656                         devmode.nt_dev_private = NULL;
2657                 }
2658         }
2659
2660         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2661         if (!*nt_devmode) {
2662                 SAFE_FREE(devmode.nt_dev_private);
2663                 return -1;
2664         }
2665
2666         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2667         if (devmode.nt_dev_private)
2668                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2669
2670         return len;
2671 }
2672
2673 /****************************************************************************
2674  Allocate and initialize a new slot.
2675 ***************************************************************************/
2676  
2677 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2678 {
2679         NT_PRINTER_KEY  *d;
2680         int             key_index;
2681         
2682         if ( !name || !data )
2683                 return -1;
2684
2685         /* allocate another slot in the NT_PRINTER_KEY array */
2686         
2687         if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2688                 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2689                 return -1;
2690         }
2691
2692         data->keys = d;
2693         
2694         key_index = data->num_keys;
2695         
2696         /* initialze new key */
2697         
2698         data->keys[key_index].name = talloc_strdup( data, name );
2699         
2700         if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) ) 
2701                 return -1;
2702         
2703         data->num_keys++;
2704
2705         DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2706         
2707         return key_index;
2708 }
2709
2710 /****************************************************************************
2711  search for a registry key name in the existing printer data
2712  ***************************************************************************/
2713
2714 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2715 {
2716         int i;
2717         
2718         for ( i=0; i<data->num_keys; i++ ) {
2719                 if ( strequal( data->keys[i].name, name ) ) {
2720                 
2721                         /* cleanup memory */
2722                         
2723                         TALLOC_FREE( data->keys[i].name );
2724                         TALLOC_FREE( data->keys[i].values );
2725                         
2726                         /* if not the end of the array, move remaining elements down one slot */
2727                         
2728                         data->num_keys--;
2729                         if ( data->num_keys && (i < data->num_keys) )
2730                                 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2731                                 
2732                         break;
2733                 }
2734         }
2735         
2736
2737         return data->num_keys;
2738 }
2739
2740 /****************************************************************************
2741  search for a registry key name in the existing printer data
2742  ***************************************************************************/
2743  
2744 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2745 {
2746         int             key_index = -1;
2747         int             i;
2748         
2749         if ( !data || !name )
2750                 return -1;
2751
2752         DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2753
2754         /* loop over all existing keys */
2755         
2756         for ( i=0; i<data->num_keys; i++ ) {
2757                 if ( strequal(data->keys[i].name, name) ) {
2758                         DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2759                         key_index = i;
2760                         break;
2761                 
2762                 }
2763         }
2764         
2765         return key_index;
2766 }
2767
2768 /****************************************************************************
2769  ***************************************************************************/
2770
2771 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2772 {
2773         int     i, j;
2774         int     key_len;
2775         int     num_subkeys = 0;
2776         char    *p;
2777         fstring *subkeys_ptr = NULL;
2778         fstring subkeyname;
2779         
2780         *subkeys = NULL;
2781
2782         if ( !data )
2783                 return 0;
2784
2785         if ( !key )
2786                 return -1;
2787
2788         /* special case of asking for the top level printer data registry key names */
2789
2790         if ( strlen(key) == 0 ) {
2791                 for ( i=0; i<data->num_keys; i++ ) {
2792                 
2793                         /* found a match, so allocate space and copy the name */
2794                         
2795                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2796                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 
2797                                         num_subkeys+1));
2798                                 return -1;
2799                         }
2800                         
2801                         fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2802                         num_subkeys++;
2803                 }
2804
2805                 goto done;
2806         }
2807                 
2808         /* asking for the subkeys of some key */
2809         /* subkey paths are stored in the key name using '\' as the delimiter */
2810
2811         for ( i=0; i<data->num_keys; i++ ) {
2812                 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2813                         
2814                         /* if we found the exact key, then break */
2815                         key_len = strlen( key );
2816                         if ( strlen(data->keys[i].name) == key_len )
2817                                 break;
2818                         
2819                         /* get subkey path */
2820
2821                         p = data->keys[i].name + key_len;
2822                         if ( *p == '\\' )
2823                                 p++;
2824                         fstrcpy( subkeyname, p );
2825                         if ( (p = strchr( subkeyname, '\\' )) )
2826                                 *p = '\0';
2827                         
2828                         /* don't add a key more than once */
2829                         
2830                         for ( j=0; j<num_subkeys; j++ ) {
2831                                 if ( strequal( subkeys_ptr[j], subkeyname ) )
2832                                         break;
2833                         }
2834                         
2835                         if ( j != num_subkeys )
2836                                 continue;
2837
2838                         /* found a match, so allocate space and copy the name */
2839                         
2840                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2841                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 
2842                                         num_subkeys+1));
2843                                 return 0;
2844                         }
2845                         
2846                         fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2847                         num_subkeys++;
2848                 }
2849                 
2850         }
2851         
2852         /* return error if the key was not found */
2853         
2854         if ( i == data->num_keys ) {
2855                 SAFE_FREE(subkeys_ptr);
2856                 return -1;
2857         }
2858         
2859 done:
2860         /* tag off the end */
2861         
2862         if (num_subkeys)
2863                 fstrcpy(subkeys_ptr[num_subkeys], "" );
2864         
2865         *subkeys = subkeys_ptr;
2866
2867         return num_subkeys;
2868 }
2869
2870 #ifdef HAVE_ADS
2871 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name, 
2872                             const char *sz)
2873 {
2874         smb_ucs2_t conv_str[1024];
2875         size_t str_size;
2876
2877         regval_ctr_delvalue(ctr, val_name);
2878         str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2879                              STR_TERMINATE | STR_NOALIGN);
2880         regval_ctr_addvalue(ctr, val_name, REG_SZ, 
2881                             (char *) conv_str, str_size);
2882 }
2883
2884 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name, 
2885                                uint32 dword)
2886 {
2887         regval_ctr_delvalue(ctr, val_name);
2888         regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2889                             (char *) &dword, sizeof(dword));
2890 }
2891
2892 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2893                               BOOL b)
2894 {
2895         uint8 bin_bool = (b ? 1 : 0);
2896         regval_ctr_delvalue(ctr, val_name);
2897         regval_ctr_addvalue(ctr, val_name, REG_BINARY, 
2898                             (char *) &bin_bool, sizeof(bin_bool));
2899 }
2900
2901 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2902                                          const char *multi_sz)
2903 {
2904         smb_ucs2_t *conv_strs = NULL;
2905         size_t str_size;
2906
2907         /* a multi-sz has to have a null string terminator, i.e., the last
2908            string must be followed by two nulls */
2909         str_size = strlen(multi_sz) + 2;
2910         conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2911         if (!conv_strs) {
2912                 return;
2913         }
2914
2915         /* Change to byte units. */
2916         str_size *= sizeof(smb_ucs2_t);
2917         push_ucs2(NULL, conv_strs, multi_sz, str_size, 
2918                   STR_TERMINATE | STR_NOALIGN);
2919
2920         regval_ctr_delvalue(ctr, val_name);
2921         regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ, 
2922                             (char *) conv_strs, str_size);      
2923         safe_free(conv_strs);
2924         
2925 }
2926
2927 /****************************************************************************
2928  * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2929  *
2930  * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2931  * @return BOOL indicating success or failure
2932  ***************************************************************************/
2933
2934 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2935 {
2936         REGVAL_CTR *ctr = NULL;
2937         fstring longname;
2938         fstring dnssuffix;
2939         char *allocated_string = NULL;
2940         const char *ascii_str;
2941         int i;
2942
2943         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2944                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2945         ctr = info2->data->keys[i].values;
2946
2947         map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2948         map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2949
2950         /* we make the assumption that the netbios name is the same 
2951            as the DNS name sinc ethe former will be what we used to 
2952            join the domain */
2953
2954         if ( get_mydnsdomname( dnssuffix ) )
2955                 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2956         else
2957                 fstrcpy( longname, global_myname() );
2958                 
2959         map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2960
2961         asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2962         map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2963         SAFE_FREE(allocated_string);
2964
2965         map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2966         map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2967         map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2968         map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2969         map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2970         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2971         map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2972         map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2973         map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2974
2975         map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2976                           (info2->attributes & 
2977                            PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2978
2979         switch (info2->attributes & 0x3) {
2980         case 0:
2981                 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2982                 break;
2983         case 1:
2984                 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2985                 break;
2986         case 2:
2987                 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2988                 break;
2989         default:
2990                 ascii_str = "unknown";
2991         }
2992         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2993
2994         return True;
2995 }
2996
2997 /*****************************************************************
2998  ****************************************************************/
2999
3000 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2, 
3001                                struct GUID guid)
3002 {
3003         int i;
3004         REGVAL_CTR *ctr=NULL;
3005         UNISTR2 unistr_guid;
3006
3007         /* find the DsSpooler key */
3008         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3009                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3010         ctr = info2->data->keys[i].values;
3011
3012         regval_ctr_delvalue(ctr, "objectGUID");
3013
3014         /* We used to store this as a REG_BINARY but that causes
3015            Vista to whine */
3016
3017         ZERO_STRUCT( unistr_guid );     
3018         init_unistr2( &unistr_guid, smb_uuid_string_static(guid),
3019                       UNI_STR_TERMINATE );
3020
3021         regval_ctr_addvalue(ctr, "objectGUID", REG_SZ, 
3022                             (char *)unistr_guid.buffer, 
3023                             unistr_guid.uni_max_len*2);
3024         
3025 }
3026
3027 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3028                                      NT_PRINTER_INFO_LEVEL *printer)
3029 {
3030         ADS_STATUS ads_rc;
3031         LDAPMessage *res;
3032         char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3033         char *srv_dn_utf8, **srv_cn_utf8;
3034         TALLOC_CTX *ctx;
3035         ADS_MODLIST mods;
3036         const char *attrs[] = {"objectGUID", NULL};
3037         struct GUID guid;
3038         WERROR win_rc = WERR_OK;
3039
3040         DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3041
3042         /* figure out where to publish */
3043         ads_find_machine_acct(ads, &res, global_myname());
3044
3045         /* We use ldap_get_dn here as we need the answer
3046          * in utf8 to call ldap_explode_dn(). JRA. */
3047
3048         srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3049         if (!srv_dn_utf8) {
3050                 ads_destroy(&ads);
3051                 return WERR_SERVER_UNAVAILABLE;
3052         }
3053         ads_msgfree(ads, res);
3054         srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3055         if (!srv_cn_utf8) {
3056                 ldap_memfree(srv_dn_utf8);
3057                 ads_destroy(&ads);
3058                 return WERR_SERVER_UNAVAILABLE;
3059         }
3060         /* Now convert to CH_UNIX. */
3061         if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
3062                 ldap_memfree(srv_dn_utf8);
3063                 ldap_memfree(srv_cn_utf8);
3064                 ads_destroy(&ads);
3065                 return WERR_SERVER_UNAVAILABLE;
3066         }
3067         if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
3068                 ldap_memfree(srv_dn_utf8);
3069                 ldap_memfree(srv_cn_utf8);
3070                 ads_destroy(&ads);
3071                 SAFE_FREE(srv_dn);
3072                 return WERR_SERVER_UNAVAILABLE;
3073         }
3074
3075         ldap_memfree(srv_dn_utf8);
3076         ldap_memfree(srv_cn_utf8);
3077
3078         srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3079         if (!srv_cn_escaped) {
3080                 SAFE_FREE(srv_cn_0);
3081                 ldap_memfree(srv_dn_utf8);
3082                 ads_destroy(&ads);
3083                 return WERR_SERVER_UNAVAILABLE;
3084         }
3085         sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3086         if (!sharename_escaped) {
3087                 SAFE_FREE(srv_cn_escaped);
3088                 SAFE_FREE(srv_cn_0);
3089                 ldap_memfree(srv_dn_utf8);
3090                 ads_destroy(&ads);
3091                 return WERR_SERVER_UNAVAILABLE;
3092         }
3093
3094
3095         asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3096
3097         SAFE_FREE(srv_dn);
3098         SAFE_FREE(srv_cn_0);
3099         SAFE_FREE(srv_cn_escaped);
3100         SAFE_FREE(sharename_escaped);
3101
3102         /* build the ads mods */
3103         ctx = talloc_init("nt_printer_publish_ads");
3104         if (ctx == NULL) {
3105                 SAFE_FREE(prt_dn);
3106                 return WERR_NOMEM;
3107         }
3108
3109         mods = ads_init_mods(ctx);
3110
3111         if (mods == NULL) {
3112                 SAFE_FREE(prt_dn);
3113                 talloc_destroy(ctx);
3114                 return WERR_NOMEM;
3115         }
3116
3117         get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3118         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, 
3119                     printer->info_2->sharename);
3120
3121         /* publish it */
3122         ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3123         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
3124                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3125
3126         if (!ADS_ERR_OK(ads_rc))
3127                 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3128         
3129         talloc_destroy(ctx);
3130
3131         /* retreive the guid and store it locally */
3132         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3133                 ZERO_STRUCT(guid);
3134                 ads_pull_guid(ads, res, &guid);
3135                 ads_msgfree(ads, res);
3136                 store_printer_guid(printer->info_2, guid);
3137                 win_rc = mod_a_printer(printer, 2);
3138         } 
3139
3140         SAFE_FREE(prt_dn);
3141         return win_rc;
3142 }
3143
3144 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3145                                        NT_PRINTER_INFO_LEVEL *printer)
3146 {
3147         ADS_STATUS ads_rc;
3148         LDAPMessage *res;
3149         char *prt_dn = NULL;
3150
3151         DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3152
3153         /* remove the printer from the directory */
3154         ads_rc = ads_find_printer_on_server(ads, &res, 
3155                             printer->info_2->sharename, global_myname());
3156
3157         if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
3158                 prt_dn = ads_get_dn(ads, res);
3159                 if (!prt_dn) {
3160                         ads_msgfree(ads, res);
3161                         return WERR_NOMEM;
3162                 }
3163                 ads_rc = ads_del_dn(ads, prt_dn);
3164                 ads_memfree(ads, prt_dn);
3165         }
3166
3167         ads_msgfree(ads, res);
3168         return WERR_OK;
3169 }
3170
3171 /****************************************************************************
3172  * Publish a printer in the directory
3173  *
3174  * @param snum describing printer service
3175  * @return WERROR indicating status of publishing
3176  ***************************************************************************/
3177
3178 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3179 {
3180         ADS_STATUS ads_rc;
3181         ADS_STRUCT *ads = NULL;
3182         NT_PRINTER_INFO_LEVEL *printer = NULL;
3183         WERROR win_rc;
3184
3185         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3186         if (!W_ERROR_IS_OK(win_rc))
3187                 goto done;
3188
3189         switch (action) {
3190         case SPOOL_DS_PUBLISH:
3191         case SPOOL_DS_UPDATE:
3192                 /* set the DsSpooler info and attributes */
3193                 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3194                         win_rc = WERR_NOMEM;
3195                         goto done;
3196                 }
3197
3198                 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3199                 break;
3200         case SPOOL_DS_UNPUBLISH:
3201                 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3202                 break;
3203         default:
3204                 win_rc = WERR_NOT_SUPPORTED;
3205                 goto done;
3206         }
3207
3208         win_rc = mod_a_printer(printer, 2);
3209         if (!W_ERROR_IS_OK(win_rc)) {
3210                 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3211                 goto done;
3212         }
3213
3214         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3215         if (!ads) {
3216                 DEBUG(3, ("ads_init() failed\n"));
3217                 win_rc = WERR_SERVER_UNAVAILABLE;
3218                 goto done;
3219         }
3220         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3221         SAFE_FREE(ads->auth.password);
3222         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3223                 NULL, NULL);
3224
3225         /* ads_connect() will find the DC for us */                                         
3226         ads_rc = ads_connect(ads);
3227         if (!ADS_ERR_OK(ads_rc)) {
3228                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3229                 win_rc = WERR_ACCESS_DENIED;
3230                 goto done;
3231         }
3232
3233         switch (action) {
3234         case SPOOL_DS_PUBLISH:
3235         case SPOOL_DS_UPDATE:
3236                 win_rc = nt_printer_publish_ads(ads, printer);
3237                 break;
3238         case SPOOL_DS_UNPUBLISH:
3239                 win_rc = nt_printer_unpublish_ads(ads, printer);
3240                 break;
3241         }
3242
3243 done:
3244         free_a_printer(&printer, 2);
3245         ads_destroy(&ads);
3246         return win_rc;
3247 }
3248
3249 WERROR check_published_printers(void)
3250 {
3251         ADS_STATUS ads_rc;
3252         ADS_STRUCT *ads = NULL;
3253         int snum;
3254         int n_services = lp_numservices();
3255         NT_PRINTER_INFO_LEVEL *printer = NULL;
3256
3257         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3258         if (!ads) {
3259                 DEBUG(3, ("ads_init() failed\n"));
3260                 return WERR_SERVER_UNAVAILABLE;
3261         }
3262         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3263         SAFE_FREE(ads->auth.password);
3264         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3265                 NULL, NULL);
3266
3267         /* ads_connect() will find the DC for us */                                         
3268         ads_rc = ads_connect(ads);
3269         if (!ADS_ERR_OK(ads_rc)) {
3270                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3271                 ads_destroy(&ads);
3272                 ads_kdestroy("MEMORY:prtpub_cache");
3273                 return WERR_ACCESS_DENIED;
3274         }
3275
3276         for (snum = 0; snum < n_services; snum++) {
3277                 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3278                         continue;
3279
3280                 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3281                                                 lp_servicename(snum))) &&
3282                     (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3283                         nt_printer_publish_ads(ads, printer);
3284
3285                 free_a_printer(&printer, 2);
3286         }
3287
3288         ads_destroy(&ads);
3289         ads_kdestroy("MEMORY:prtpub_cache");
3290         return WERR_OK;
3291 }
3292
3293 BOOL is_printer_published(Printer_entry *print_hnd, int snum, 
3294                           struct GUID *guid)
3295 {
3296         NT_PRINTER_INFO_LEVEL *printer = NULL;
3297         REGVAL_CTR *ctr;
3298         REGISTRY_VALUE *guid_val;
3299         WERROR win_rc;
3300         int i;
3301         BOOL ret = False;
3302
3303         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3304
3305         if (!W_ERROR_IS_OK(win_rc) ||
3306             !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3307             ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3308             !(ctr = printer->info_2->data->keys[i].values) ||
3309             !(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) 
3310         {
3311                 free_a_printer(&printer, 2);
3312                 return False;
3313         }
3314
3315         /* fetching printer guids really ought to be a separate function. */
3316
3317         if ( guid ) {   
3318                 fstring guid_str;
3319                 
3320                 /* We used to store the guid as REG_BINARY, then swapped 
3321                    to REG_SZ for Vista compatibility so check for both */
3322
3323                 switch ( regval_type(guid_val) ){
3324                 case REG_SZ:            
3325                         rpcstr_pull( guid_str, regval_data_p(guid_val), 
3326                                      sizeof(guid_str)-1, -1, STR_TERMINATE );
3327                         ret = smb_string_to_uuid( guid_str, guid );
3328                         break;                  
3329                 case REG_BINARY:
3330                         if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3331                                 ret = False;
3332                                 break;
3333                         }
3334                         memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3335                         break;
3336                 default:
3337                         DEBUG(0,("is_printer_published: GUID value stored as "
3338                                  "invaluid type (%d)\n", regval_type(guid_val) ));                      
3339                         break;
3340                 }
3341         }
3342
3343         free_a_printer(&printer, 2);
3344         return ret;
3345 }
3346 #else
3347 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3348 {
3349         return WERR_OK;
3350 }
3351
3352 WERROR check_published_printers(void)
3353 {
3354         return WERR_OK;
3355 }
3356
3357 BOOL is_printer_published(Printer_entry *print_hnd, int snum, 
3358                           struct GUID *guid)
3359 {
3360         return False;
3361 }
3362 #endif /* HAVE_ADS */
3363
3364 /****************************************************************************
3365  ***************************************************************************/
3366  
3367 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3368 {
3369         NT_PRINTER_DATA *data;
3370         int             i;
3371         int             removed_keys = 0;
3372         int             empty_slot;
3373         
3374         data = p2->data;
3375         empty_slot = data->num_keys;
3376
3377         if ( !key )
3378                 return WERR_INVALID_PARAM;
3379         
3380         /* remove all keys */
3381
3382         if ( !strlen(key) ) {
3383         
3384                 TALLOC_FREE( data );
3385
3386                 p2->data = NULL;
3387
3388                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3389                         p2->printername ));
3390         
3391                 return WERR_OK;
3392         }
3393
3394         /* remove a specific key (and all subkeys) */
3395         
3396         for ( i=0; i<data->num_keys; i++ ) {
3397                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3398                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3399                                 data->keys[i].name));
3400                 
3401                         TALLOC_FREE( data->keys[i].name );
3402                         TALLOC_FREE( data->keys[i].values );
3403
3404                         /* mark the slot as empty */
3405
3406                         ZERO_STRUCTP( &data->keys[i] );
3407                 }
3408         }
3409
3410         /* find the first empty slot */
3411
3412         for ( i=0; i<data->num_keys; i++ ) {
3413                 if ( !data->keys[i].name ) {
3414                         empty_slot = i;
3415                         removed_keys++;
3416                         break;
3417                 }
3418         }
3419
3420         if ( i == data->num_keys )
3421                 /* nothing was removed */
3422                 return WERR_INVALID_PARAM;
3423
3424         /* move everything down */
3425         
3426         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3427                 if ( data->keys[i].name ) {
3428                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) ); 
3429                         ZERO_STRUCTP( &data->keys[i] );
3430                         empty_slot++;
3431                         removed_keys++;
3432                 }
3433         }
3434
3435         /* update count */
3436                 
3437         data->num_keys -= removed_keys;
3438
3439         /* sanity check to see if anything is left */
3440
3441         if ( !data->num_keys ) {
3442                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3443
3444                 SAFE_FREE( data->keys );
3445                 ZERO_STRUCTP( data );
3446         }
3447
3448         return WERR_OK;
3449 }
3450
3451 /****************************************************************************
3452  ***************************************************************************/
3453  
3454 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3455 {
3456         WERROR          result = WERR_OK;
3457         int             key_index;
3458         
3459         /* we must have names on non-zero length */
3460         
3461         if ( !key || !*key|| !value || !*value )
3462                 return WERR_INVALID_NAME;
3463                 
3464         /* find the printer key first */
3465
3466         key_index = lookup_printerkey( p2->data, key );
3467         if ( key_index == -1 )
3468                 return WERR_OK;
3469         
3470         /* make sure the value exists so we can return the correct error code */
3471         
3472         if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3473                 return WERR_BADFILE;
3474                 
3475         regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3476         
3477         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3478                 key, value ));
3479         
3480         return result;
3481 }
3482
3483 /****************************************************************************
3484  ***************************************************************************/
3485  
3486 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value, 
3487                            uint32 type, uint8 *data, int real_len )
3488 {
3489         WERROR          result = WERR_OK;
3490         int             key_index;
3491
3492         /* we must have names on non-zero length */
3493         
3494         if ( !key || !*key|| !value || !*value )
3495                 return WERR_INVALID_NAME;
3496                 
3497         /* find the printer key first */
3498         
3499         key_index = lookup_printerkey( p2->data, key );
3500         if ( key_index == -1 )
3501                 key_index = add_new_printer_key( p2->data, key );
3502                 
3503         if ( key_index == -1 )
3504                 return WERR_NOMEM;
3505         
3506         regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3507                 type, (const char *)data, real_len );
3508         
3509         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3510                 key, value, type, real_len  ));
3511         
3512         return result;
3513 }
3514
3515 /****************************************************************************
3516  ***************************************************************************/
3517  
3518 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3519 {
3520         int             key_index;
3521
3522         if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3523                 return NULL;
3524
3525         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3526                 key, value ));
3527
3528         return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3529 }
3530
3531 /****************************************************************************
3532  Unpack a list of registry values frem the TDB
3533  ***************************************************************************/
3534  
3535 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3536 {
3537         int             len = 0;
3538         uint32          type;
3539         pstring         string, valuename, keyname;
3540         char            *str;
3541         int             size;
3542         uint8           *data_p;
3543         REGISTRY_VALUE  *regval_p;
3544         int             key_index;
3545
3546         /* add the "PrinterDriverData" key first for performance reasons */
3547         
3548         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3549
3550         /* loop and unpack the rest of the registry values */
3551         
3552         while ( True ) {
3553         
3554                 /* check to see if there are any more registry values */
3555                 
3556                 regval_p = NULL;
3557                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);         
3558                 if ( !regval_p ) 
3559                         break;
3560
3561                 /* unpack the next regval */
3562                 
3563                 len += tdb_unpack(buf+len, buflen-len, "fdB",
3564                                   string,
3565                                   &type,
3566                                   &size,
3567                                   &data_p);
3568
3569                 /* lookup for subkey names which have a type of REG_NONE */
3570                 /* there's no data with this entry */
3571
3572                 if ( type == REG_NONE ) {
3573                         if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3574                                 add_new_printer_key( printer_data, string );
3575                         continue;
3576                 }
3577         
3578                 /*
3579                  * break of the keyname from the value name.  
3580                  * Valuenames can have embedded '\'s so be careful.
3581                  * only support one level of keys.  See the 
3582                  * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3583                  * -- jerry
3584                  */     
3585                  
3586                 str = strchr_m( string, '\\');
3587                 
3588                 /* Put in "PrinterDriverData" is no key specified */
3589                 
3590                 if ( !str ) {
3591                         pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3592                         pstrcpy( valuename, string );
3593                 }
3594                 else {
3595                         *str = '\0';
3596                         pstrcpy( keyname, string );
3597                         pstrcpy( valuename, str+1 );
3598                 }
3599                         
3600                 /* see if we need a new key */
3601                 
3602                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3603                         key_index = add_new_printer_key( printer_data, keyname );
3604                         
3605                 if ( key_index == -1 ) {
3606                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3607                                 keyname));
3608                         break;
3609                 }
3610                 
3611                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3612
3613                 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.  
3614                    Thanks to Martin Zielinski for the hint. */
3615
3616                 if ( type == REG_BINARY && 
3617                      strequal( keyname, SPOOL_DSSPOOLER_KEY ) && 
3618                      strequal( valuename, "objectGUID" ) ) 
3619                 {
3620                         struct GUID guid;
3621                         UNISTR2 unistr_guid;
3622
3623                         ZERO_STRUCT( unistr_guid );
3624                         
3625                         /* convert the GUID to a UNICODE string */
3626                         
3627                         memcpy( &guid, data_p, sizeof(struct GUID) );
3628                         
3629                         init_unistr2( &unistr_guid, smb_uuid_string_static(guid), 
3630                                       UNI_STR_TERMINATE );
3631                         
3632                         regval_ctr_addvalue( printer_data->keys[key_index].values, 
3633                                              valuename, REG_SZ, 
3634                                              (const char *)unistr_guid.buffer, 
3635                                              unistr_guid.uni_str_len*2 );
3636
3637                 } else {
3638                         /* add the value */
3639
3640                         regval_ctr_addvalue( printer_data->keys[key_index].values, 
3641                                              valuename, type, (const char *)data_p, 
3642                                              size );
3643                 }
3644                 
3645
3646                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3647
3648         }
3649
3650         return len;
3651 }
3652
3653 /****************************************************************************
3654  ***************************************************************************/
3655
3656 static void map_to_os2_driver(fstring drivername)
3657 {
3658         static BOOL initialised=False;
3659         static fstring last_from,last_to;
3660         char *mapfile = lp_os2_driver_map();
3661         char **lines = NULL;
3662         int numlines = 0;
3663         int i;
3664
3665         if (!strlen(drivername))
3666                 return;
3667
3668         if (!*mapfile)
3669                 return;
3670
3671         if (!initialised) {
3672                 *last_from = *last_to = 0;
3673                 initialised = True;
3674         }
3675
3676         if (strequal(drivername,last_from)) {
3677                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3678                 fstrcpy(drivername,last_to);
3679                 return;
3680         }
3681
3682         lines = file_lines_load(mapfile, &numlines,0);
3683         if (numlines == 0 || lines == NULL) {
3684                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3685                 SAFE_FREE(lines);
3686                 return;
3687         }
3688
3689         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3690
3691         for( i = 0; i < numlines; i++) {
3692                 char *nt_name = lines[i];
3693                 char *os2_name = strchr(nt_name,'=');
3694
3695                 if (!os2_name)
3696                         continue;
3697
3698                 *os2_name++ = 0;
3699
3700                 while (isspace(*nt_name))
3701                         nt_name++;
3702
3703                 if (!*nt_name || strchr("#;",*nt_name))
3704                         continue;
3705
3706                 {
3707                         int l = strlen(nt_name);
3708                         while (l && isspace(nt_name[l-1])) {
3709                                 nt_name[l-1] = 0;
3710                                 l--;
3711                         }
3712                 }
3713
3714                 while (isspace(*os2_name))
3715                         os2_name++;
3716
3717                 {
3718                         int l = strlen(os2_name);
3719                         while (l && isspace(os2_name[l-1])) {
3720                                 os2_name[l-1] = 0;
3721                                 l--;
3722                         }
3723                 }
3724
3725                 if (strequal(nt_name,drivername)) {
3726                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3727                         fstrcpy(last_from,drivername);
3728                         fstrcpy(last_to,os2_name);
3729                         fstrcpy(drivername,os2_name);
3730                         file_lines_free(lines);
3731                         return;
3732                 }
3733         }
3734
3735         file_lines_free(lines);
3736 }
3737
3738 /****************************************************************************
3739  Get a default printer info 2 struct.
3740 ****************************************************************************/
3741 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
3742 {
3743         int snum = lp_servicenumber(sharename);
3744
3745         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3746         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s", 
3747                 servername, sharename);
3748         fstrcpy(info->sharename, sharename);
3749         fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3750
3751         /* by setting the driver name to an empty string, a local NT admin
3752            can now run the **local** APW to install a local printer driver
3753            for a Samba shared printer in 2.2.  Without this, drivers **must** be 
3754            installed on the Samba server for NT clients --jerry */
3755 #if 0   /* JERRY --do not uncomment-- */
3756         if (!*info->drivername)
3757                 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3758 #endif
3759
3760
3761         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3762
3763         pstrcpy(info->comment, "");
3764         fstrcpy(info->printprocessor, "winprint");
3765         fstrcpy(info->datatype, "RAW");
3766
3767 #ifdef HAVE_CUPS
3768         if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {           
3769                 /* Pull the location and comment strings from cups if we don't
3770                    already have one */
3771                 if ( !strlen(info->location) || !strlen(info->comment) )
3772                         cups_pull_comment_location( info );
3773         }
3774 #endif
3775
3776         info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3777
3778         info->starttime = 0; /* Minutes since 12:00am GMT */
3779         info->untiltime = 0; /* Minutes since 12:00am GMT */
3780         info->priority = 1;
3781         info->default_priority = 1;
3782         info->setuptime = (uint32)time(NULL);
3783
3784         /*
3785          * I changed this as I think it is better to have a generic
3786          * DEVMODE than to crash Win2k explorer.exe   --jerry
3787          * See the HP Deskjet 990c Win2k drivers for an example.
3788          *
3789          * However the default devmode appears to cause problems
3790          * with the HP CLJ 8500 PCL driver.  Hence the addition of
3791          * the "default devmode" parameter   --jerry 22/01/2002
3792          */
3793
3794         if (lp_default_devmode(snum)) {
3795                 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
3796                         goto fail;
3797                 }
3798         } else {
3799                 info->devmode = NULL;
3800         }
3801
3802         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3803                 goto fail;
3804         }
3805
3806         return WERR_OK;
3807
3808 fail:
3809         if (info->devmode)
3810                 free_nt_devicemode(&info->devmode);
3811
3812         return WERR_ACCESS_DENIED;
3813 }
3814
3815 /****************************************************************************
3816 ****************************************************************************/
3817 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
3818 {
3819         int len = 0;
3820         int snum = lp_servicenumber(sharename);
3821         TDB_DATA kbuf, dbuf;
3822         fstring printername;
3823         char adevice[MAXDEVICENAME];
3824                 
3825         kbuf = make_printer_tdbkey( sharename );
3826
3827         dbuf = tdb_fetch(tdb_printers, kbuf);
3828         if (!dbuf.dptr) {
3829                 return get_a_printer_2_default(info, servername, sharename);
3830         }
3831
3832         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3833                         &info->attributes,
3834                         &info->priority,
3835                         &info->default_priority,
3836                         &info->starttime,
3837                         &info->untiltime,
3838                         &info->status,
3839                         &info->cjobs,
3840                         &info->averageppm,
3841                         &info->changeid,
3842                         &info->c_setprinter,
3843                         &info->setuptime,
3844                         info->servername,
3845                         info->printername,
3846                         info->sharename,
3847                         info->portname,
3848                         info->drivername,
3849                         info->comment,
3850                         info->location,
3851                         info->sepfile,
3852                         info->printprocessor,
3853                         info->datatype,
3854                         info->parameters);
3855
3856         /* Samba has to have shared raw drivers. */
3857         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3858         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3859
3860         /* Restore the stripped strings. */
3861         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3862
3863         if ( lp_force_printername(snum) ) {
3864                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3865         } else {
3866                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3867         }
3868
3869         fstrcpy(info->printername, printername);
3870
3871 #ifdef HAVE_CUPS
3872         if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {           
3873                 /* Pull the location and comment strings from cups if we don't
3874                    already have one */
3875                 if ( !strlen(info->location) || !strlen(info->comment) )
3876                         cups_pull_comment_location( info );
3877         }
3878 #endif
3879
3880         len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
3881
3882         /*
3883          * Some client drivers freak out if there is a NULL devmode
3884          * (probably the driver is not checking before accessing 
3885          * the devmode pointer)   --jerry
3886          *
3887          * See comments in get_a_printer_2_default()
3888          */
3889
3890         if (lp_default_devmode(snum) && !info->devmode) {
3891                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3892                         printername));
3893                 info->devmode = construct_nt_devicemode(printername);
3894         }
3895
3896         slprintf( adevice, sizeof(adevice), "%s", info->printername );
3897         if (info->devmode) {
3898                 fstrcpy(info->devmode->devicename, adevice);    
3899         }
3900
3901         if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
3902                 DEBUG(0,("unpack_values: talloc() failed!\n"));
3903                 SAFE_FREE(dbuf.dptr);
3904                 return WERR_NOMEM;
3905         }
3906         len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
3907
3908         /* This will get the current RPC talloc context, but we should be
3909            passing this as a parameter... fixme... JRA ! */
3910
3911         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3912                 SAFE_FREE(dbuf.dptr);
3913                 return WERR_NOMEM;
3914         }
3915
3916         /* Fix for OS/2 drivers. */
3917
3918         if (get_remote_arch() == RA_OS2) {
3919                 map_to_os2_driver(info->drivername);
3920         }
3921
3922         SAFE_FREE(dbuf.dptr);
3923
3924         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3925                  sharename, info->printername, info->drivername));
3926
3927         return WERR_OK; 
3928 }
3929
3930 /****************************************************************************
3931  Debugging function, dump at level 6 the struct in the logs.
3932 ****************************************************************************/
3933 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3934 {
3935         uint32 result;
3936         NT_PRINTER_INFO_LEVEL_2 *info2;
3937         
3938         DEBUG(106,("Dumping printer at level [%d]\n", level));
3939         
3940         switch (level) {
3941                 case 2:
3942                 {
3943                         if (printer->info_2 == NULL)
3944                                 result=5;
3945                         else
3946                         {
3947                                 info2=printer->info_2;
3948                         
3949                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3950                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3951                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3952                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3953                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3954                                 DEBUGADD(106,("status:[%d]\n", info2->status));
3955                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3956                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3957                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3958                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3959                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3960
3961                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3962                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3963                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3964                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3965                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3966                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3967                                 DEBUGADD(106,("location:[%s]\n", info2->location));
3968                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3969                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3970                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3971                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3972                                 result=0;
3973                         }
3974                         break;
3975                 }
3976                 default:
3977                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3978                         result=1;
3979                         break;
3980         }
3981         
3982         return result;
3983 }
3984
3985 /****************************************************************************
3986  Update the changeid time.
3987  This is SO NASTY as some drivers need this to change, others need it
3988  static. This value will change every second, and I must hope that this
3989  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3990  UTAH ! JRA.
3991 ****************************************************************************/
3992
3993 static uint32 rev_changeid(void)
3994 {
3995         struct timeval tv;
3996
3997         get_process_uptime(&tv);
3998
3999 #if 1   /* JERRY */
4000         /* Return changeid as msec since spooler restart */
4001         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4002 #else
4003         /*
4004          * This setting seems to work well but is too untested
4005          * to replace the above calculation.  Left in for experiementation
4006          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
4007          */
4008         return tv.tv_sec * 10 + tv.tv_usec / 100000;
4009 #endif
4010 }
4011
4012
4013 /*
4014  * The function below are the high level ones.
4015  * only those ones must be called from the spoolss code.
4016  * JFM.
4017  */
4018
4019 /****************************************************************************
4020  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4021 ****************************************************************************/
4022
4023 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4024 {
4025         WERROR result;
4026         
4027         dump_a_printer(printer, level); 
4028         
4029         switch (level) {
4030                 case 2:
4031                 {
4032                         /*
4033                          * Update the changestamp.  Emperical tests show that the
4034                          * ChangeID is always updated,but c_setprinter is  
4035                          *  global spooler variable (not per printer).
4036                          */
4037
4038                         /* ChangeID **must** be increasing over the lifetime
4039                            of client's spoolss service in order for the
4040                            client's cache to show updates */
4041
4042                         printer->info_2->changeid = rev_changeid();
4043
4044                         /*
4045                          * Because one day someone will ask:
4046                          * NT->NT       An admin connection to a remote
4047                          *              printer show changes imeediately in
4048                          *              the properities dialog
4049                          *      
4050                          *              A non-admin connection will only show the
4051                          *              changes after viewing the properites page
4052                          *              2 times.  Seems to be related to a
4053                          *              race condition in the client between the spooler
4054                          *              updating the local cache and the Explorer.exe GUI
4055                          *              actually displaying the properties.
4056                          *
4057                          *              This is fixed in Win2k.  admin/non-admin
4058                          *              connections both display changes immediately.
4059                          *
4060                          * 14/12/01     --jerry
4061                          */
4062
4063                         result=update_a_printer_2(printer->info_2);
4064                         
4065                         break;
4066                 }
4067                 default:
4068                         result=WERR_UNKNOWN_LEVEL;
4069                         break;
4070         }
4071         
4072         return result;
4073 }
4074
4075 /****************************************************************************
4076  Initialize printer devmode & data with previously saved driver init values.
4077 ****************************************************************************/
4078
4079 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4080 {
4081         int                     len = 0;
4082         pstring                 key;
4083         TDB_DATA                dbuf;
4084         NT_PRINTER_INFO_LEVEL_2 info;
4085
4086
4087         ZERO_STRUCT(info);
4088
4089         /*
4090          * Delete any printer data 'values' already set. When called for driver
4091          * replace, there will generally be some, but during an add printer, there
4092          * should not be any (if there are delete them).
4093          */
4094          
4095         if ( info_ptr->data )
4096                 delete_all_printer_data( info_ptr, "" );
4097         
4098         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
4099
4100         dbuf = tdb_fetch_bystring(tdb_drivers, key);
4101         if (!dbuf.dptr) {
4102                 /*
4103                  * When changing to a driver that has no init info in the tdb, remove
4104                  * the previous drivers init info and leave the new on blank.
4105                  */
4106                 free_nt_devicemode(&info_ptr->devmode);
4107                 return False;
4108         }
4109         
4110         /*
4111          * Get the saved DEVMODE..
4112          */
4113          
4114         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4115
4116         /*
4117          * The saved DEVMODE contains the devicename from the printer used during
4118          * the initialization save. Change it to reflect the new printer.
4119          */
4120          
4121         if ( info.devmode ) {
4122                 ZERO_STRUCT(info.devmode->devicename);
4123                 fstrcpy(info.devmode->devicename, info_ptr->printername);
4124         }
4125
4126         /*
4127          * NT/2k does not change out the entire DeviceMode of a printer
4128          * when changing the driver.  Only the driverextra, private, & 
4129          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
4130          *
4131          * Later examination revealed that Windows NT/2k does reset the
4132          * the printer's device mode, bit **only** when you change a 
4133          * property of the device mode such as the page orientation.
4134          * --jerry
4135          */
4136
4137
4138         /* Bind the saved DEVMODE to the new the printer */
4139          
4140         free_nt_devicemode(&info_ptr->devmode);
4141         info_ptr->devmode = info.devmode;
4142
4143         DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4144                 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4145
4146         /* Add the printer data 'values' to the new printer */
4147
4148         if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4149                 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4150                 return False;
4151         }
4152          
4153         len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4154         
4155
4156         SAFE_FREE(dbuf.dptr);
4157
4158         return True;    
4159 }
4160
4161 /****************************************************************************
4162  Initialize printer devmode & data with previously saved driver init values.
4163  When a printer is created using AddPrinter, the drivername bound to the
4164  printer is used to lookup previously saved driver initialization info, which
4165  is bound to the new printer.
4166 ****************************************************************************/
4167
4168 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4169 {
4170         BOOL result = False;
4171         
4172         switch (level) {
4173                 case 2:
4174                         result = set_driver_init_2(printer->info_2);
4175                         break;
4176                         
4177                 default:
4178                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
4179                                 level));
4180                         break;
4181         }
4182         
4183         return result;
4184 }
4185
4186 /****************************************************************************
4187  Delete driver init data stored for a specified driver
4188 ****************************************************************************/
4189
4190 BOOL del_driver_init(char *drivername)
4191 {
4192         pstring key;
4193
4194         if (!drivername || !*drivername) {
4195                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4196                 return False;
4197         }
4198
4199         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
4200
4201         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
4202
4203         return (tdb_delete_bystring(tdb_drivers, key) == 0);
4204 }
4205
4206 /****************************************************************************
4207  Pack up the DEVMODE and values for a printer into a 'driver init' entry 
4208  in the tdb. Note: this is different from the driver entry and the printer
4209  entry. There should be a single driver init entry for each driver regardless
4210  of whether it was installed from NT or 2K. Technically, they should be
4211  different, but they work out to the same struct.
4212 ****************************************************************************/
4213
4214 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4215 {
4216         pstring key;
4217         uint8 *buf;
4218         int buflen, len, ret;
4219         TDB_DATA dbuf;
4220
4221         buf = NULL;
4222         buflen = 0;
4223
4224  again: 
4225         len = 0;
4226         len += pack_devicemode(info->devmode, buf+len, buflen-len);
4227
4228         len += pack_values( info->data, buf+len, buflen-len );
4229
4230         if (buflen < len) {
4231                 buf = (uint8 *)SMB_REALLOC(buf, len);
4232                 if (!buf) {
4233                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4234                         ret = -1;
4235                         goto done;
4236                 }
4237                 buflen = len;
4238                 goto again;
4239         }
4240
4241         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4242
4243         dbuf.dptr = buf;
4244         dbuf.dsize = len;
4245
4246         ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4247
4248 done:
4249         if (ret == -1)
4250                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4251
4252         SAFE_FREE(buf);
4253
4254         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4255                  info->sharename, info->drivername));
4256
4257         return ret;
4258 }
4259
4260 /****************************************************************************
4261  Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4262 ****************************************************************************/
4263
4264 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4265 {
4266         uint32 result;
4267         
4268         dump_a_printer(printer, level); 
4269         
4270         switch (level) {
4271                 case 2:
4272                         result = update_driver_init_2(printer->info_2);
4273                         break;
4274                 default:
4275                         result = 1;
4276                         break;
4277         }
4278         
4279         return result;
4280 }
4281
4282 /****************************************************************************
4283  Convert the printer data value, a REG_BINARY array, into an initialization 
4284  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4285  got to keep the endians happy :).
4286 ****************************************************************************/
4287
4288 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4289 {
4290         BOOL       result = False;
4291         prs_struct ps;
4292         DEVICEMODE devmode;
4293
4294         ZERO_STRUCT(devmode);
4295
4296         prs_init(&ps, 0, ctx, UNMARSHALL);
4297         ps.data_p      = (char *)data;
4298         ps.buffer_size = data_len;
4299
4300         if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4301                 result = convert_devicemode("", &devmode, &nt_devmode);
4302         else
4303                 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4304
4305         return result;
4306 }
4307
4308 /****************************************************************************
4309  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4310
4311  1. Use the driver's config DLL to this UNC printername and:
4312     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4313     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4314  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4315
4316  The last step triggers saving the "driver initialization" information for
4317  this printer into the tdb. Later, new printers that use this driver will
4318  have this initialization information bound to them. This simulates the
4319  driver initialization, as if it had run on the Samba server (as it would
4320  have done on NT).
4321
4322  The Win32 client side code requirement sucks! But until we can run arbitrary
4323  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4324  
4325  It would have been easier to use SetPrinter because all the UNMARSHALLING of
4326  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4327  about it and you will realize why.  JRR 010720
4328 ****************************************************************************/
4329
4330 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4331 {
4332         WERROR        status       = WERR_OK;
4333         TALLOC_CTX    *ctx         = NULL;
4334         NT_DEVICEMODE *nt_devmode  = NULL;
4335         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4336         
4337         /*
4338          * When the DEVMODE is already set on the printer, don't try to unpack it.
4339          */
4340         DEBUG(8,("save_driver_init_2: Enter...\n"));
4341         
4342         if ( !printer->info_2->devmode && data_len ) {
4343                 /*
4344                  * Set devmode on printer info, so entire printer initialization can be
4345                  * saved to tdb.
4346                  */
4347
4348                 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4349                         return WERR_NOMEM;
4350
4351                 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4352                         status = WERR_NOMEM;
4353                         goto done;
4354                 }
4355         
4356                 ZERO_STRUCTP(nt_devmode);
4357
4358                 /*
4359                  * The DEVMODE is held in the 'data' component of the param in raw binary.
4360                  * Convert it to to a devmode structure
4361                  */
4362                 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4363                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4364                         status = WERR_INVALID_PARAM;
4365                         goto done;
4366                 }
4367
4368                 printer->info_2->devmode = nt_devmode;
4369         }
4370
4371         /*
4372          * Pack up and add (or update) the DEVMODE and any current printer data to
4373          * a 'driver init' element in the tdb
4374          * 
4375          */
4376
4377         if ( update_driver_init(printer, 2) != 0 ) {
4378                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4379                 status = WERR_NOMEM;
4380                 goto done;
4381         }
4382         
4383         /*
4384          * If driver initialization info was successfully saved, set the current 
4385          * printer to match it. This allows initialization of the current printer 
4386          * as well as the driver.
4387          */
4388         status = mod_a_printer(printer, 2);
4389         if (!W_ERROR_IS_OK(status)) {
4390                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4391                                   printer->info_2->printername));
4392         }
4393         
4394   done:
4395         talloc_destroy(ctx);
4396         free_nt_devicemode( &nt_devmode );
4397         
4398         printer->info_2->devmode = tmp_devmode;
4399
4400         return status;
4401 }
4402
4403 /****************************************************************************
4404  Update the driver init info (DEVMODE and specifics) for a printer
4405 ****************************************************************************/
4406
4407 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4408 {
4409         WERROR status = WERR_OK;
4410         
4411         switch (level) {
4412                 case 2:
4413                         status = save_driver_init_2( printer, data, data_len );
4414                         break;
4415                 default:
4416                         status = WERR_UNKNOWN_LEVEL;
4417                         break;
4418         }
4419         
4420         return status;
4421 }
4422
4423 /****************************************************************************
4424  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4425
4426  Previously the code had a memory allocation problem because it always
4427  used the TALLOC_CTX from the Printer_entry*.   This context lasts 
4428  as a long as the original handle is open.  So if the client made a lot 
4429  of getprinter[data]() calls, the memory usage would climb.  Now we use
4430  a short lived TALLOC_CTX for printer_info_2 objects returned.  We 
4431  still use the Printer_entry->ctx for maintaining the cache copy though
4432  since that object must live as long as the handle by definition.  
4433                                                     --jerry
4434
4435 ****************************************************************************/
4436
4437 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, 
4438                         const char *sharename)
4439 {
4440         WERROR result;
4441         fstring servername;
4442         
4443         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4444
4445         if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4446                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4447                 return WERR_NOMEM;
4448         }
4449
4450         switch (level) {
4451                 case 2:
4452                         if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4453                                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4454                                 TALLOC_FREE( *pp_printer );
4455                                 return WERR_NOMEM;
4456                         }
4457
4458                         if ( print_hnd ) 
4459                                 fstrcpy( servername, print_hnd->servername );
4460                         else {
4461                                 fstrcpy( servername, "%L" );
4462                                 standard_sub_basic( "", "", servername,
4463                                                     sizeof(servername)-1 );
4464                         }
4465
4466                         result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4467         
4468                         
4469                         /* we have a new printer now.  Save it with this handle */
4470                         
4471                         if ( !W_ERROR_IS_OK(result) ) {
4472                                 TALLOC_FREE( *pp_printer );
4473                                 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", 
4474                                         sharename, (unsigned int)level, dos_errstr(result)));
4475                                 return result;
4476                         }
4477
4478                         dump_a_printer( *pp_printer, level);
4479                         
4480                         break;
4481                         
4482                 default:
4483                         TALLOC_FREE( *pp_printer );
4484                         return WERR_UNKNOWN_LEVEL;
4485         }
4486         
4487         return WERR_OK;
4488 }
4489
4490 /****************************************************************************
4491  Deletes a NT_PRINTER_INFO_LEVEL struct.
4492 ****************************************************************************/
4493
4494 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4495 {
4496         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4497
4498         if ( !printer )
4499                 return 0;
4500         
4501         switch (level) {
4502                 case 2:
4503                         if ( printer->info_2 ) 
4504                                 free_nt_printer_info_level_2(&printer->info_2);
4505                         break;
4506
4507                 default:
4508                         DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4509                         return 1;
4510         }
4511
4512         TALLOC_FREE(*pp_printer);
4513
4514         return 0;
4515 }
4516
4517 /****************************************************************************
4518 ****************************************************************************/
4519 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4520 {
4521         uint32 result;
4522         DEBUG(104,("adding a printer at level [%d]\n", level));
4523         dump_a_printer_driver(driver, level);
4524         
4525         switch (level) {
4526                 case 3:
4527                         result=add_a_printer_driver_3(driver.info_3);
4528                         break;
4529
4530                 case 6:
4531                         result=add_a_printer_driver_6(driver.info_6);
4532                         break;
4533
4534                 default:
4535                         result=1;
4536                         break;
4537         }
4538         
4539         return result;
4540 }
4541 /****************************************************************************
4542 ****************************************************************************/
4543
4544 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4545                             fstring drivername, const char *architecture, uint32 version)
4546 {
4547         WERROR result;
4548         
4549         switch (level) {
4550                 case 3:
4551                         /* Sometime we just want any version of the driver */
4552                         
4553                         if ( version == DRIVER_ANY_VERSION ) {
4554                                 /* look for Win2k first and then for NT4 */
4555                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4556                                                 architecture, 3);
4557                                                 
4558                                 if ( !W_ERROR_IS_OK(result) ) {
4559                                         result = get_a_printer_driver_3( &driver->info_3, 
4560                                                         drivername, architecture, 2 );
4561                                 }
4562                         } else {
4563                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4564                                         architecture, version);                         
4565                         }
4566                         break;
4567                         
4568                 default:
4569                         result=W_ERROR(1);
4570                         break;
4571         }
4572         
4573         if (W_ERROR_IS_OK(result))
4574                 dump_a_printer_driver(*driver, level);
4575                 
4576         return result;
4577 }
4578
4579 /****************************************************************************
4580 ****************************************************************************/
4581 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4582 {
4583         uint32 result;
4584         
4585         switch (level) {
4586                 case 3:
4587                 {
4588                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4589                         if (driver.info_3 != NULL)
4590                         {
4591                                 info3=driver.info_3;
4592                                 SAFE_FREE(info3->dependentfiles);
4593                                 ZERO_STRUCTP(info3);
4594                                 SAFE_FREE(info3);
4595                                 result=0;
4596                         } else {
4597                                 result=4;
4598                         }
4599                         break;
4600                 }
4601                 case 6:
4602                 {
4603                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4604                         if (driver.info_6 != NULL) {
4605                                 info6=driver.info_6;
4606                                 SAFE_FREE(info6->dependentfiles);
4607                                 SAFE_FREE(info6->previousnames);
4608                                 ZERO_STRUCTP(info6);
4609                                 SAFE_FREE(info6);
4610                                 result=0;
4611                         } else {
4612                                 result=4;
4613                         }
4614                         break;
4615                 }
4616                 default:
4617                         result=1;
4618                         break;
4619         }
4620         return result;
4621 }
4622
4623
4624 /****************************************************************************
4625   Determine whether or not a particular driver is currently assigned
4626   to a printer
4627 ****************************************************************************/
4628
4629 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4630 {
4631         int snum;
4632         int n_services = lp_numservices();
4633         NT_PRINTER_INFO_LEVEL *printer = NULL;
4634         BOOL in_use = False;
4635
4636         if ( !info_3 ) 
4637                 return False;
4638
4639         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4640         
4641         /* loop through the printers.tdb and check for the drivername */
4642         
4643         for (snum=0; snum<n_services && !in_use; snum++) {
4644                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4645                         continue;
4646                 
4647                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4648                         continue;
4649                 
4650                 if ( strequal(info_3->name, printer->info_2->drivername) ) 
4651                         in_use = True;
4652                 
4653                 free_a_printer( &printer, 2 );
4654         }
4655         
4656         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4657         
4658         if ( in_use ) {
4659                 NT_PRINTER_DRIVER_INFO_LEVEL d;
4660                 WERROR werr;
4661                 
4662                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4663                 
4664                 /* we can still remove the driver if there is one of 
4665                    "Windows NT x86" version 2 or 3 left */
4666                    
4667                 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4668                         werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );                       
4669                 }
4670                 else {
4671                         switch ( info_3->cversion ) {
4672                         case 2:
4673                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4674                                 break;
4675                         case 3: 
4676                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4677                                 break;
4678                         default:
4679                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n", 
4680                                         info_3->cversion));
4681                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4682                                 break;
4683                         }
4684                 }
4685
4686                 /* now check the error code */
4687                                 
4688                 if ( W_ERROR_IS_OK(werr) ) {
4689                         /* it's ok to remove the driver, we have other architctures left */
4690                         in_use = False;
4691                         free_a_printer_driver( d, 3 );
4692                 }
4693         }
4694         
4695         /* report that the driver is not in use by default */
4696         
4697         return in_use;
4698 }
4699
4700
4701 /**********************************************************************
4702  Check to see if a ogiven file is in use by *info
4703  *********************************************************************/
4704  
4705 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4706 {
4707         int i = 0;
4708         
4709         if ( !info )
4710                 return False;
4711                 
4712         if ( strequal(file, info->driverpath) )
4713                 return True;
4714
4715         if ( strequal(file, info->datafile) )
4716                 return True;
4717
4718         if ( strequal(file, info->configfile) )
4719                 return True;
4720
4721         if ( strequal(file, info->helpfile) )
4722                 return True;
4723         
4724         /* see of there are any dependent files to examine */
4725         
4726         if ( !info->dependentfiles )
4727                 return False;
4728         
4729         while ( *info->dependentfiles[i] ) {
4730                 if ( strequal(file, info->dependentfiles[i]) )
4731                         return True;
4732                 i++;
4733         }
4734         
4735         return False;
4736
4737 }
4738
4739 /**********************************************************************
4740  Utility function to remove the dependent file pointed to by the 
4741  input parameter from the list 
4742  *********************************************************************/
4743
4744 static void trim_dependent_file( fstring files[], int idx )
4745 {
4746         
4747         /* bump everything down a slot */
4748
4749         while( *files[idx+1] ) {
4750                 fstrcpy( files[idx], files[idx+1] );
4751                 idx++;
4752         }
4753         
4754         *files[idx] = '\0';
4755
4756         return; 
4757 }
4758
4759 /**********************************************************************
4760  Check if any of the files used by src are also used by drv 
4761  *********************************************************************/
4762
4763 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, 
4764                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4765 {
4766         BOOL    in_use = False;
4767         int     i = 0;
4768         
4769         if ( !src || !drv )
4770                 return False;
4771                 
4772         /* check each file.  Remove it from the src structure if it overlaps */
4773         
4774         if ( drv_file_in_use(src->driverpath, drv) ) {
4775                 in_use = True;
4776                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4777                 fstrcpy( src->driverpath, "" );
4778         }
4779                 
4780         if ( drv_file_in_use(src->datafile, drv) ) {
4781                 in_use = True;
4782                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4783                 fstrcpy( src->datafile, "" );
4784         }
4785                 
4786         if ( drv_file_in_use(src->configfile, drv) ) {
4787                 in_use = True;
4788                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4789                 fstrcpy( src->configfile, "" );
4790         }
4791                 
4792         if ( drv_file_in_use(src->helpfile, drv) ) {
4793                 in_use = True;
4794                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4795                 fstrcpy( src->helpfile, "" );
4796         }
4797         
4798         /* are there any dependentfiles to examine? */
4799         
4800         if ( !src->dependentfiles )
4801                 return in_use;
4802                 
4803         while ( *src->dependentfiles[i] ) {
4804                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4805                         in_use = True;
4806                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4807                         trim_dependent_file( src->dependentfiles, i );
4808                 } else
4809                         i++;
4810         }               
4811                 
4812         return in_use;
4813 }
4814
4815 /****************************************************************************
4816   Determine whether or not a particular driver files are currently being 
4817   used by any other driver.  
4818   
4819   Return value is True if any files were in use by other drivers
4820   and False otherwise.
4821   
4822   Upon return, *info has been modified to only contain the driver files
4823   which are not in use
4824 ****************************************************************************/
4825
4826 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4827 {
4828         int                             i;
4829         int                             ndrivers;
4830         uint32                          version;
4831         fstring                         *list = NULL;
4832         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
4833         
4834         if ( !info )
4835                 return False;
4836         
4837         version = info->cversion;
4838         
4839         /* loop over all driver versions */
4840         
4841         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4842         
4843         /* get the list of drivers */
4844                 
4845         list = NULL;
4846         ndrivers = get_ntdrivers(&list, info->environment, version);
4847                 
4848         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
4849                 ndrivers, info->environment, version));
4850
4851         /* check each driver for overlap in files */
4852                 
4853         for (i=0; i<ndrivers; i++) {
4854                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4855                         
4856                 ZERO_STRUCT(driver);
4857                         
4858                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4859                         SAFE_FREE(list);
4860                         return True;
4861                 }
4862                         
4863                 /* check if d2 uses any files from d1 */
4864                 /* only if this is a different driver than the one being deleted */
4865                         
4866                 if ( !strequal(info->name, driver.info_3->name) ) {
4867                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
4868                                 free_a_printer_driver(driver, 3);
4869                                 SAFE_FREE( list );
4870                                 return True;
4871                         }
4872                 }
4873         
4874                 free_a_printer_driver(driver, 3);
4875         }       
4876         
4877         SAFE_FREE(list);
4878         
4879         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4880         
4881         driver.info_3 = info;
4882         
4883         if ( DEBUGLEVEL >= 20 )
4884                 dump_a_printer_driver( driver, 3 );
4885         
4886         return False;
4887 }
4888
4889 /****************************************************************************
4890   Actually delete the driver files.  Make sure that 
4891   printer_driver_files_in_use() return False before calling 
4892   this.
4893 ****************************************************************************/
4894
4895 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4896 {
4897         int i = 0;
4898         char *s;
4899         pstring file;
4900         connection_struct *conn;
4901         DATA_BLOB null_pw;
4902         NTSTATUS nt_status;
4903         fstring res_type;
4904         SMB_STRUCT_STAT  st;
4905
4906         if ( !info_3 )
4907                 return False;
4908                 
4909         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4910         
4911         /*
4912          * Connect to the print$ share under the same account as the 
4913          * user connected to the rpc pipe. Note we must be root to 
4914          * do this.
4915          */
4916          
4917         null_pw = data_blob_null;
4918         fstrcpy(res_type, "A:");
4919         become_root();
4920         conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4921         unbecome_root();
4922         
4923         if ( !conn ) {
4924                 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4925                 return False;
4926         }
4927
4928         if ( !CAN_WRITE(conn) ) {
4929                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4930                 return False;
4931         }
4932
4933         /* Save who we are - we are temporarily becoming the connection user. */
4934
4935         if ( !become_user(conn, conn->vuid) ) {
4936                 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4937                 return False;
4938         }
4939
4940         /* now delete the files; must strip the '\print$' string from 
4941            fron of path                                                */
4942         
4943         if ( *info_3->driverpath ) {
4944                 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4945                         pstrcpy( file, s );
4946                         driver_unix_convert(conn,file,&st);
4947                         DEBUG(10,("deleting driverfile [%s]\n", s));
4948                         unlink_internals(conn, NULL, 0, file, False);
4949                 }
4950         }
4951                 
4952         if ( *info_3->configfile ) {
4953                 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4954                         pstrcpy( file, s );
4955                         driver_unix_convert(conn,file,&st);
4956                         DEBUG(10,("deleting configfile [%s]\n", s));
4957                         unlink_internals(conn, NULL, 0, file, False);
4958                 }
4959         }
4960         
4961         if ( *info_3->datafile ) {
4962                 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4963                         pstrcpy( file, s );
4964                         driver_unix_convert(conn,file,&st);
4965                         DEBUG(10,("deleting datafile [%s]\n", s));
4966                         unlink_internals(conn, NULL, 0, file, False);
4967                 }
4968         }
4969         
4970         if ( *info_3->helpfile ) {
4971                 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4972                         pstrcpy( file, s );
4973                         driver_unix_convert(conn,file,&st);
4974                         DEBUG(10,("deleting helpfile [%s]\n", s));
4975                         unlink_internals(conn, NULL, 0, file, False);
4976                 }
4977         }
4978         
4979         /* check if we are done removing files */
4980         
4981         if ( info_3->dependentfiles ) {
4982                 while ( info_3->dependentfiles[i][0] ) {
4983                         char *p;
4984
4985                         /* bypass the "\print$" portion of the path */
4986                         
4987                         if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4988                                 pstrcpy( file, p );
4989                                 driver_unix_convert(conn,file,&st);
4990                                 DEBUG(10,("deleting dependent file [%s]\n", file));
4991                                 unlink_internals(conn, NULL, 0, file, False);
4992                         }
4993                         
4994                         i++;
4995                 }
4996         }
4997
4998         unbecome_user();
4999         
5000         return True;
5001 }
5002
5003 /****************************************************************************
5004  Remove a printer driver from the TDB.  This assumes that the the driver was
5005  previously looked up.
5006  ***************************************************************************/
5007
5008 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
5009                               uint32 version, BOOL delete_files )
5010 {
5011         pstring         key;
5012         const char     *arch;
5013         TDB_DATA        dbuf;
5014         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
5015
5016         /* delete the tdb data first */
5017
5018         arch = get_short_archi(info_3->environment);
5019         if (!arch) {
5020                 return WERR_UNKNOWN_PRINTER_DRIVER;
5021         }
5022         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
5023                 arch, version, info_3->name);
5024
5025         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5026                 key, delete_files ? "TRUE" : "FALSE" ));
5027
5028         ctr.info_3 = info_3;
5029         dump_a_printer_driver( ctr, 3 );
5030
5031         /* check if the driver actually exists for this environment */
5032         
5033         dbuf = tdb_fetch_bystring( tdb_drivers, key );
5034         if ( !dbuf.dptr ) {
5035                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5036                 return WERR_UNKNOWN_PRINTER_DRIVER;
5037         }
5038                 
5039         SAFE_FREE( dbuf.dptr );
5040         
5041         /* ok... the driver exists so the delete should return success */
5042                 
5043         if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5044                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5045                 return WERR_ACCESS_DENIED;
5046         }
5047
5048         /*
5049          * now delete any associated files if delete_files == True
5050          * even if this part failes, we return succes because the
5051          * driver doesn not exist any more
5052          */
5053
5054         if ( delete_files )
5055                 delete_driver_files( info_3, user );
5056                         
5057                 
5058         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5059
5060         return WERR_OK;
5061         }
5062         
5063 /****************************************************************************
5064  Store a security desc for a printer.
5065 ****************************************************************************/
5066
5067 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5068 {
5069         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5070         SEC_DESC_BUF *old_secdesc_ctr = NULL;
5071         prs_struct ps;
5072         TALLOC_CTX *mem_ctx = NULL;
5073         TDB_DATA kbuf;
5074         WERROR status;
5075
5076         mem_ctx = talloc_init("nt_printing_setsec");
5077         if (mem_ctx == NULL)
5078                 return WERR_NOMEM;
5079
5080         /* The old owner and group sids of the security descriptor are not
5081            present when new ACEs are added or removed by changing printer
5082            permissions through NT.  If they are NULL in the new security
5083            descriptor then copy them over from the old one. */
5084
5085         if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5086                 DOM_SID *owner_sid, *group_sid;
5087                 SEC_ACL *dacl, *sacl;
5088                 SEC_DESC *psd = NULL;
5089                 size_t size;
5090
5091                 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5092                         status = WERR_NOMEM;
5093                         goto out;
5094                 }
5095
5096                 /* Pick out correct owner and group sids */
5097
5098                 owner_sid = secdesc_ctr->sd->owner_sid ?
5099                         secdesc_ctr->sd->owner_sid :
5100                         old_secdesc_ctr->sd->owner_sid;
5101
5102                 group_sid = secdesc_ctr->sd->group_sid ?
5103                         secdesc_ctr->sd->group_sid :
5104                         old_secdesc_ctr->sd->group_sid;
5105
5106                 dacl = secdesc_ctr->sd->dacl ?
5107                         secdesc_ctr->sd->dacl :
5108                         old_secdesc_ctr->sd->dacl;
5109
5110                 sacl = secdesc_ctr->sd->sacl ?
5111                         secdesc_ctr->sd->sacl :
5112                         old_secdesc_ctr->sd->sacl;
5113
5114                 /* Make a deep copy of the security descriptor */
5115
5116                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5117                                     owner_sid, group_sid,
5118                                     sacl,
5119                                     dacl,
5120                                     &size);
5121
5122                 if (!psd) {
5123                         status = WERR_NOMEM;
5124                         goto out;
5125                 }
5126
5127                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5128         }
5129
5130         if (!new_secdesc_ctr) {
5131                 new_secdesc_ctr = secdesc_ctr;
5132         }
5133
5134         /* Store the security descriptor in a tdb */
5135
5136         prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sd) +
5137                  sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
5138
5139         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
5140                              &ps, 1)) {
5141                 status = WERR_BADFUNC;
5142                 goto out;
5143         }
5144
5145         kbuf = make_printers_secdesc_tdbkey( sharename );
5146
5147         if (tdb_prs_store(tdb_printers, kbuf, &ps)==0) {
5148                 status = WERR_OK;
5149         } else {
5150                 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5151                 status = WERR_BADFUNC;
5152         }
5153
5154         /* Free malloc'ed memory */
5155
5156  out:
5157
5158         prs_mem_free(&ps);
5159         if (mem_ctx)
5160                 talloc_destroy(mem_ctx);
5161         return status;
5162 }
5163
5164 /****************************************************************************
5165  Construct a default security descriptor buffer for a printer.
5166 ****************************************************************************/
5167
5168 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5169 {
5170         SEC_ACE ace[5]; /* max number of ace entries */
5171         int i = 0;
5172         SEC_ACCESS sa;
5173         SEC_ACL *psa = NULL;
5174         SEC_DESC_BUF *sdb = NULL;
5175         SEC_DESC *psd = NULL;
5176         DOM_SID adm_sid;
5177         size_t sd_size;
5178
5179         /* Create an ACE where Everyone is allowed to print */
5180
5181         init_sec_access(&sa, PRINTER_ACE_PRINT);
5182         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5183                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5184
5185         /* Add the domain admins group if we are a DC */
5186         
5187         if ( IS_DC ) {
5188                 DOM_SID domadmins_sid;
5189                 
5190                 sid_copy(&domadmins_sid, get_global_sam_sid());
5191                 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5192                 
5193                 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5194                 init_sec_ace(&ace[i++], &domadmins_sid, 
5195                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5196                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5197                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5198                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5199         }
5200         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5201                 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5202
5203                 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5204                 init_sec_ace(&ace[i++], &adm_sid, 
5205                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5206                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5207                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5208                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5209         }
5210
5211         /* add BUILTIN\Administrators as FULL CONTROL */
5212
5213         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5214         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 
5215                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 
5216                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5217         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 
5218                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5219                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5220
5221         /* Make the security descriptor owned by the BUILTIN\Administrators */
5222
5223         /* The ACL revision number in rpc_secdesc.h differs from the one
5224            created by NT when setting ACE entries in printer
5225            descriptors.  NT4 complains about the property being edited by a
5226            NT5 machine. */
5227
5228         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5229                 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5230                         &global_sid_Builtin_Administrators, 
5231                         &global_sid_Builtin_Administrators,
5232                         NULL, psa, &sd_size);
5233         }
5234
5235         if (!psd) {
5236                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5237                 return NULL;
5238         }
5239
5240         sdb = make_sec_desc_buf(ctx, sd_size, psd);
5241
5242         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5243                  (unsigned int)sd_size));
5244
5245         return sdb;
5246 }
5247
5248 /****************************************************************************
5249  Get a security desc for a printer.
5250 ****************************************************************************/
5251
5252 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5253 {
5254         prs_struct ps;
5255         TDB_DATA kbuf;
5256         char *temp;
5257
5258         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5259                 sharename = temp + 1;
5260         }
5261
5262         ZERO_STRUCT(ps);
5263
5264         /* Fetch security descriptor from tdb */
5265
5266         kbuf = make_printers_secdesc_tdbkey( sharename  );
5267
5268         if (tdb_prs_fetch(tdb_printers, kbuf, &ps, ctx)!=0 ||
5269             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5270
5271                 prs_mem_free(&ps);
5272
5273                 DEBUG(4,("using default secdesc for %s\n", sharename));
5274
5275                 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5276                         return False;
5277                 }
5278
5279                 /* Save default security descriptor for later */
5280
5281                 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sd) +
5282                                 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5283
5284                 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5285                         tdb_prs_store(tdb_printers, kbuf, &ps);
5286                 }
5287
5288                 prs_mem_free(&ps);
5289
5290                 return True;
5291         }
5292
5293         prs_mem_free(&ps);
5294
5295         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5296            this security descriptor has been created when winbindd was
5297            down.  Take ownership of security descriptor. */
5298
5299         if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5300                 DOM_SID owner_sid;
5301
5302                 /* Change sd owner to workgroup administrator */
5303
5304                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5305                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
5306                         SEC_DESC *psd = NULL;
5307                         size_t size;
5308
5309                         /* Create new sd */
5310
5311                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5312
5313                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5314                                             &owner_sid,
5315                                             (*secdesc_ctr)->sd->group_sid,
5316                                             (*secdesc_ctr)->sd->sacl,
5317                                             (*secdesc_ctr)->sd->dacl,
5318                                             &size);
5319
5320                         if (!psd) {
5321                                 return False;
5322                         }
5323
5324                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5325                         if (!new_secdesc_ctr) {
5326                                 return False;
5327                         }
5328
5329                         /* Swap with other one */
5330
5331                         *secdesc_ctr = new_secdesc_ctr;
5332
5333                         /* Set it */
5334
5335                         nt_printing_setsec(sharename, *secdesc_ctr);
5336                 }
5337         }
5338
5339         if (DEBUGLEVEL >= 10) {
5340                 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5341                 int i;
5342
5343                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
5344                            sharename, the_acl->num_aces));
5345
5346                 for (i = 0; i < the_acl->num_aces; i++) {
5347                         fstring sid_str;
5348
5349                         sid_to_string(sid_str, &the_acl->aces[i].trustee);
5350
5351                         DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5352                                    the_acl->aces[i].type, the_acl->aces[i].flags, 
5353                                    the_acl->aces[i].access_mask)); 
5354                 }
5355         }
5356
5357         return True;
5358 }
5359
5360 /* error code:
5361         0: everything OK
5362         1: level not implemented
5363         2: file doesn't exist
5364         3: can't allocate memory
5365         4: can't free memory
5366         5: non existant struct
5367 */
5368
5369 /*
5370         A printer and a printer driver are 2 different things.
5371         NT manages them separatelly, Samba does the same.
5372         Why ? Simply because it's easier and it makes sense !
5373         
5374         Now explanation: You have 3 printers behind your samba server,
5375         2 of them are the same make and model (laser A and B). But laser B
5376         has an 3000 sheet feeder and laser A doesn't such an option.
5377         Your third printer is an old dot-matrix model for the accounting :-).
5378         
5379         If the /usr/local/samba/lib directory (default dir), you will have
5380         5 files to describe all of this.
5381         
5382         3 files for the printers (1 by printer):
5383                 NTprinter_laser A
5384                 NTprinter_laser B
5385                 NTprinter_accounting
5386         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5387                 NTdriver_printer model X
5388                 NTdriver_printer model Y
5389
5390 jfm: I should use this comment for the text file to explain
5391         same thing for the forms BTW.
5392         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5393
5394 */
5395
5396 /* Convert generic access rights to printer object specific access rights.
5397    It turns out that NT4 security descriptors use generic access rights and
5398    NT5 the object specific ones. */
5399
5400 void map_printer_permissions(SEC_DESC *sd)
5401 {
5402         int i;
5403
5404         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5405                 se_map_generic(&sd->dacl->aces[i].access_mask,
5406                                &printer_generic_mapping);
5407         }
5408 }
5409
5410 /****************************************************************************
5411  Check a user has permissions to perform the given operation.  We use the
5412  permission constants defined in include/rpc_spoolss.h to check the various
5413  actions we perform when checking printer access.
5414
5415    PRINTER_ACCESS_ADMINISTER:
5416        print_queue_pause, print_queue_resume, update_printer_sec,
5417        update_printer, spoolss_addprinterex_level_2,
5418        _spoolss_setprinterdata
5419
5420    PRINTER_ACCESS_USE:
5421        print_job_start
5422
5423    JOB_ACCESS_ADMINISTER:
5424        print_job_delete, print_job_pause, print_job_resume,
5425        print_queue_purge
5426
5427   Try access control in the following order (for performance reasons):
5428     1)  root ans SE_PRINT_OPERATOR can do anything (easy check) 
5429     2)  check security descriptor (bit comparisons in memory)
5430     3)  "printer admins" (may result in numerous calls to winbind)
5431
5432  ****************************************************************************/
5433 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5434 {
5435         SEC_DESC_BUF *secdesc = NULL;
5436         uint32 access_granted;
5437         NTSTATUS status;
5438         BOOL result;
5439         const char *pname;
5440         TALLOC_CTX *mem_ctx = NULL;
5441         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5442         
5443         /* If user is NULL then use the current_user structure */
5444
5445         if (!user)
5446                 user = &current_user;
5447
5448         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5449
5450         if ( user->ut.uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5451                 return True;
5452         }
5453
5454         /* Get printer name */
5455
5456         pname = PRINTERNAME(snum);
5457
5458         if (!pname || !*pname) {
5459                 errno = EACCES;
5460                 return False;
5461         }
5462
5463         /* Get printer security descriptor */
5464
5465         if(!(mem_ctx = talloc_init("print_access_check"))) {
5466                 errno = ENOMEM;
5467                 return False;
5468         }
5469
5470         if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5471                 talloc_destroy(mem_ctx);
5472                 errno = ENOMEM;
5473                 return False;
5474         }
5475
5476         if (access_type == JOB_ACCESS_ADMINISTER) {
5477                 SEC_DESC_BUF *parent_secdesc = secdesc;
5478
5479                 /* Create a child security descriptor to check permissions
5480                    against.  This is because print jobs are child objects
5481                    objects of a printer. */
5482
5483                 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sd, False);
5484
5485                 if (!secdesc) {
5486                         talloc_destroy(mem_ctx);
5487                         errno = ENOMEM;
5488                         return False;
5489                 }
5490
5491                 /* Now this is the bit that really confuses me.  The access
5492                    type needs to be changed from JOB_ACCESS_ADMINISTER to
5493                    PRINTER_ACCESS_ADMINISTER for this to work.  Something
5494                    to do with the child (job) object becoming like a
5495                    printer??  -tpot */
5496
5497                 access_type = PRINTER_ACCESS_ADMINISTER;
5498         }
5499         
5500         /* Check access */
5501         
5502         map_printer_permissions(secdesc->sd);
5503
5504         result = se_access_check(secdesc->sd, user->nt_user_token, access_type,
5505                                  &access_granted, &status);
5506
5507         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5508
5509         /* see if we need to try the printer admin list */
5510
5511         if ((access_granted == 0) &&
5512             (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
5513                                          user->nt_user_token,
5514                                          lp_printer_admin(snum)))) {
5515                 talloc_destroy(mem_ctx);
5516                 return True;
5517         }
5518
5519         talloc_destroy(mem_ctx);
5520         
5521         if (!result) {
5522                 errno = EACCES;
5523         }
5524
5525         return result;
5526 }
5527
5528 /****************************************************************************
5529  Check the time parameters allow a print operation.
5530 *****************************************************************************/
5531
5532 BOOL print_time_access_check(const char *servicename)
5533 {
5534         NT_PRINTER_INFO_LEVEL *printer = NULL;
5535         BOOL ok = False;
5536         time_t now = time(NULL);
5537         struct tm *t;
5538         uint32 mins;
5539
5540         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5541                 return False;
5542
5543         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5544                 ok = True;
5545
5546         t = gmtime(&now);
5547         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5548
5549         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5550                 ok = True;
5551
5552         free_a_printer(&printer, 2);
5553
5554         if (!ok)
5555                 errno = EACCES;
5556
5557         return ok;
5558 }
5559
5560 /****************************************************************************
5561  Fill in the servername sent in the _spoolss_open_printer_ex() call
5562 ****************************************************************************/
5563
5564 char* get_server_name( Printer_entry *printer )
5565 {
5566         return printer->servername;
5567 }
5568
5569