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