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