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