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