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