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