r16582: Fix Klocwork #1997 and all generic class of problems
[nivanova/samba-autobuild/.git] / source3 / printing / nt_printing.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2000.
6  *  Copyright (C) Gerald Carter                2002-2005.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include "includes.h"
24
25 extern struct current_user current_user;
26
27 static TDB_CONTEXT *tdb_forms; /* used for forms files */
28 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29 static TDB_CONTEXT *tdb_printers; /* used for printers files */
30
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
37  
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
41 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
42 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
43
44 /* Map generic permissions to printer object specific permissions */
45
46 GENERIC_MAPPING printer_generic_mapping = {
47         PRINTER_READ,
48         PRINTER_WRITE,
49         PRINTER_EXECUTE,
50         PRINTER_ALL_ACCESS
51 };
52
53 STANDARD_MAPPING printer_std_mapping = {
54         PRINTER_READ,
55         PRINTER_WRITE,
56         PRINTER_EXECUTE,
57         PRINTER_ALL_ACCESS
58 };
59
60 /* Map generic permissions to print server object specific permissions */
61
62 GENERIC_MAPPING printserver_generic_mapping = {
63         SERVER_READ,
64         SERVER_WRITE,
65         SERVER_EXECUTE,
66         SERVER_ALL_ACCESS
67 };
68
69 STANDARD_MAPPING printserver_std_mapping = {
70         SERVER_READ,
71         SERVER_WRITE,
72         SERVER_EXECUTE,
73         SERVER_ALL_ACCESS
74 };
75
76 /* We need one default form to support our default printer. Msoft adds the
77 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
78 array index). Letter is always first, so (for the current code) additions
79 always put things in the correct order. */
80 static const nt_forms_struct default_forms[] = {
81         {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82         {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83         {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
84         {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
85         {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
86         {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
87         {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
88         {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
89         {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90         {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91         {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
92         {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
93         {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
94         {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
95         {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
96         {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
97         {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
98         {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
99         {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
100         {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
101         {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
102         {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
103         {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
104         {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
105         {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
106         {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
107         {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
108         {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
109         {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
110         {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
111         {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
112         {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
113         {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
114         {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
115         {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
116         {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
117         {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
118         {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
119         {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
120         {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
121         {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
122         {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
123         {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
124         {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
125         {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
126         {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
127         {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
128         {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129         {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130         {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
131         {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
132         {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
133         {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
134         {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
135         {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
136         {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137         {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
138         {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
139         {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
140         {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
141         {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
142         {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
143         {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
144         {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
145         {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
146         {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
147         {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
148         {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
149         {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
150         {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
151         {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
152         {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
153         {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
154         {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
155         {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
156         {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
157         {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
158         {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
159         {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
160         {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
161         {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
162         {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
163         {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
164         {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
165         {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
166         {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
167         {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
168         {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
169         {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
170         {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
171         {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
172         {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
173         {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
174         {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
175         {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
176         {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
177         {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
178         {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
179         {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
180         {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
181         {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
182         {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
183         {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
184         {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
185         {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
186         {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
187         {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
188         {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
189         {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
190         {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
191         {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
192         {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
193         {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
194         {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
195         {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
196         {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
197         {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
198         {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
199 };
200
201 struct table_node {
202         const char      *long_archi;
203         const char      *short_archi;
204         int     version;
205 };
206  
207 #define SPL_ARCH_WIN40          "WIN40"
208 #define SPL_ARCH_W32X86         "W32X86"
209 #define SPL_ARCH_W32MIPS        "W32MIPS"
210 #define SPL_ARCH_W32ALPHA       "W32ALPHA"
211 #define SPL_ARCH_W32PPC         "W32PPC"
212 #define SPL_ARCH_IA64           "IA64"
213 #define SPL_ARCH_X64            "x64"
214
215 static const struct table_node archi_table[]= {
216
217         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
218         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
219         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
220         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
221         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
222         {"Windows IA64",         SPL_ARCH_IA64,         3 },
223         {"Windows x64",          SPL_ARCH_X64,          3 },
224         {NULL,                   "",            -1 }
225 };
226
227
228 /****************************************************************************
229  generate a new TDB_DATA key for storing a printer
230 ****************************************************************************/
231
232 static TDB_DATA make_printer_tdbkey( const char *sharename )
233 {
234         fstring share;
235         static pstring keystr;
236         TDB_DATA key;
237         
238         fstrcpy( share, sharename );
239         strlower_m( share );
240         
241         pstr_sprintf( keystr, "%s%s", PRINTERS_PREFIX, share );
242         
243         key.dptr = keystr;
244         key.dsize = strlen(keystr)+1;
245
246         return key;
247 }
248
249 /****************************************************************************
250  generate a new TDB_DATA key for storing a printer security descriptor
251 ****************************************************************************/
252
253 static char *make_printers_secdesc_tdbkey( const char* sharename  )
254 {
255         fstring share;
256         static pstring keystr;
257         
258         fstrcpy( share, sharename );
259         strlower_m( share );
260         
261         pstr_sprintf( keystr, "%s%s", SECDESC_PREFIX, share );
262
263         return keystr;
264 }
265
266 /****************************************************************************
267 ****************************************************************************/
268
269 static BOOL upgrade_to_version_3(void)
270 {
271         TDB_DATA kbuf, newkey, dbuf;
272  
273         DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
274  
275         for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
276                         newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
277
278                 dbuf = tdb_fetch(tdb_drivers, kbuf);
279
280                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
281                         DEBUG(0,("upgrade_to_version_3:moving form\n"));
282                         if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
283                                 SAFE_FREE(dbuf.dptr);
284                                 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
285                                 return False;
286                         }
287                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
288                                 SAFE_FREE(dbuf.dptr);
289                                 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
290                                 return False;
291                         }
292                 }
293  
294                 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
295                         DEBUG(0,("upgrade_to_version_3:moving printer\n"));
296                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
297                                 SAFE_FREE(dbuf.dptr);
298                                 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
299                                 return False;
300                         }
301                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
302                                 SAFE_FREE(dbuf.dptr);
303                                 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
304                                 return False;
305                         }
306                 }
307  
308                 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
309                         DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
310                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
311                                 SAFE_FREE(dbuf.dptr);
312                                 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
313                                 return False;
314                         }
315                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
316                                 SAFE_FREE(dbuf.dptr);
317                                 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
318                                 return False;
319                         }
320                 }
321  
322                 SAFE_FREE(dbuf.dptr);
323         }
324
325         return True;
326 }
327
328 /*******************************************************************
329  Fix an issue with security descriptors.  Printer sec_desc must 
330  use more than the generic bits that were previously used 
331  in <= 3.0.14a.  They must also have a owner and group SID assigned.
332  Otherwise, any printers than have been migrated to a Windows 
333  host using printmig.exe will not be accessible.
334 *******************************************************************/
335
336 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
337                             TDB_DATA data, void *state )
338 {
339         prs_struct ps;
340         SEC_DESC_BUF *sd_orig = NULL;
341         SEC_DESC_BUF *sd_new, *sd_store;
342         SEC_DESC *sec, *new_sec;
343         TALLOC_CTX *ctx = state;
344         int result, i;
345         uint32 sd_size;
346         size_t size_new_sec;
347         DOM_SID sid;
348
349         if (!data.dptr || data.dsize == 0) {
350                 return 0;
351         }
352
353         if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
354                 return 0;
355         }
356
357         /* upgrade the security descriptor */
358
359         ZERO_STRUCT( ps );
360
361         prs_init( &ps, 0, ctx, UNMARSHALL );
362         prs_give_memory( &ps, data.dptr, data.dsize, False );
363
364         if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
365                 /* delete bad entries */
366                 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si.  Deleting....\n", key.dptr ));
367                 tdb_delete( tdb_printers, key );
368                 prs_mem_free( &ps );
369                 return 0;
370         }
371
372         if (!sd_orig) {
373                 prs_mem_free( &ps );
374                 return 0;
375         }
376         sec = sd_orig->sec;
377                 
378         /* is this even valid? */
379         
380         if ( !sec->dacl ) {
381                 prs_mem_free( &ps );
382                 return 0;
383         }
384                 
385         /* update access masks */
386         
387         for ( i=0; i<sec->dacl->num_aces; i++ ) {
388                 switch ( sec->dacl->ace[i].info.mask ) {
389                         case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
390                                 sec->dacl->ace[i].info.mask = PRINTER_ACE_PRINT;
391                                 break;
392                                 
393                         case GENERIC_ALL_ACCESS:
394                                 sec->dacl->ace[i].info.mask = PRINTER_ACE_FULL_CONTROL;
395                                 break;
396                                 
397                         case READ_CONTROL_ACCESS:
398                                 sec->dacl->ace[i].info.mask = PRINTER_ACE_MANAGE_DOCUMENTS;
399                         
400                         default:        /* no change */
401                                 break;
402                 }
403         }
404
405         /* create a new SEC_DESC with the appropriate owner and group SIDs */
406
407         string_to_sid(&sid, "S-1-5-32-544" );
408         new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
409                 &sid, &sid,
410                 NULL, NULL, &size_new_sec );
411         if (!new_sec) {
412                 prs_mem_free( &ps );
413                 return 0;
414         }
415         sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
416         if (!sd_new) {
417                 prs_mem_free( &ps );
418                 return 0;
419         }
420
421         if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
422                 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
423                 prs_mem_free( &ps );
424                 return 0;
425         }
426         
427         prs_mem_free( &ps );
428
429         /* store it back */
430         
431         sd_size = sec_desc_size(sd_store->sec) + sizeof(SEC_DESC_BUF);
432         prs_init(&ps, sd_size, ctx, MARSHALL);
433
434         if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
435                 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
436                 prs_mem_free( &ps );
437                 return 0;
438         }
439
440         data.dptr = prs_data_p( &ps );
441         data.dsize = sd_size;
442         
443         result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
444
445         prs_mem_free( &ps );
446         
447         /* 0 to continue and non-zero to stop traversal */
448
449         return (result == -1);
450 }
451
452 /*******************************************************************
453 *******************************************************************/
454
455 static BOOL upgrade_to_version_4(void)
456 {
457         TALLOC_CTX *ctx;
458         int result;
459
460         DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
461
462         if ( !(ctx = talloc_init( "upgrade_to_version_4" )) ) 
463                 return False;
464
465         result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
466
467         talloc_destroy( ctx );
468
469         return ( result != -1 );
470 }
471
472 /*******************************************************************
473  Fix an issue with security descriptors.  Printer sec_desc must 
474  use more than the generic bits that were previously used 
475  in <= 3.0.14a.  They must also have a owner and group SID assigned.
476  Otherwise, any printers than have been migrated to a Windows 
477  host using printmig.exe will not be accessible.
478 *******************************************************************/
479
480 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
481                                   TDB_DATA data, void *state )
482 {
483         TDB_DATA new_key;
484         
485         if (!data.dptr || data.dsize == 0)
486                 return 0;
487
488         /* upgrade printer records and security descriptors */
489         
490         if ( strncmp( key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
491                 new_key = make_printer_tdbkey( key.dptr+strlen(PRINTERS_PREFIX) );
492         }
493         else if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
494                 new_key.dptr = make_printers_secdesc_tdbkey( key.dptr+strlen(SECDESC_PREFIX) );
495                 new_key.dsize = strlen( new_key.dptr ) + 1;
496         }
497         else {
498                 /* ignore this record */
499                 return 0;
500         }
501                 
502         /* delete the original record and store under the normalized key */
503         
504         if ( tdb_delete( the_tdb, key ) != 0 ) {
505                 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n", 
506                         key.dptr));
507                 return 1;
508         }
509         
510         if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
511                 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
512                         key.dptr));
513                 return 1;
514         }
515         
516         return 0;
517 }
518
519 /*******************************************************************
520 *******************************************************************/
521
522 static BOOL upgrade_to_version_5(void)
523 {
524         TALLOC_CTX *ctx;
525         int result;
526
527         DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
528
529         if ( !(ctx = talloc_init( "upgrade_to_version_5" )) ) 
530                 return False;
531
532         result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
533
534         talloc_destroy( ctx );
535
536         return ( result != -1 );
537 }
538
539 /****************************************************************************
540  Open the NT printing tdbs. Done once before fork().
541 ****************************************************************************/
542
543 BOOL nt_printing_init(void)
544 {
545         const char *vstring = "INFO/version";
546         WERROR win_rc;
547         int32 vers_id;
548
549         if ( tdb_drivers && tdb_printers && tdb_forms )
550                 return True;
551  
552         if (tdb_drivers)
553                 tdb_close(tdb_drivers);
554         tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
555         if (!tdb_drivers) {
556                 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
557                         lock_path("ntdrivers.tdb"), strerror(errno) ));
558                 return False;
559         }
560  
561         if (tdb_printers)
562                 tdb_close(tdb_printers);
563         tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
564         if (!tdb_printers) {
565                 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
566                         lock_path("ntprinters.tdb"), strerror(errno) ));
567                 return False;
568         }
569  
570         if (tdb_forms)
571                 tdb_close(tdb_forms);
572         tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
573         if (!tdb_forms) {
574                 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
575                         lock_path("ntforms.tdb"), strerror(errno) ));
576                 return False;
577         }
578  
579         /* handle a Samba upgrade */
580         
581         vers_id = tdb_fetch_int32(tdb_drivers, vstring);
582         if (vers_id == -1) {
583                 DEBUG(10, ("Fresh database\n"));
584                 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
585                 vers_id = NTDRIVERS_DATABASE_VERSION_5;
586         }
587
588         if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
589
590                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) { 
591                         if (!upgrade_to_version_3())
592                                 return False;
593                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
594                         vers_id = NTDRIVERS_DATABASE_VERSION_3;
595                 } 
596                 
597                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
598                         /* Written on a bigendian machine with old fetch_int code. Save as le. */
599                         /* The only upgrade between V2 and V3 is to save the version in little-endian. */
600                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
601                         vers_id = NTDRIVERS_DATABASE_VERSION_3;
602                 }
603
604                 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
605                         if ( !upgrade_to_version_4() )
606                                 return False;
607                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
608                         vers_id = NTDRIVERS_DATABASE_VERSION_4;
609                 }
610
611                 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
612                         if ( !upgrade_to_version_5() )
613                                 return False;
614                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
615                         vers_id = NTDRIVERS_DATABASE_VERSION_5;
616                 }
617
618
619                 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
620                         DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
621                         return False;
622                 }
623         }
624         
625         update_c_setprinter(True);
626
627         /*
628          * register callback to handle updating printers as new
629          * drivers are installed
630          */
631
632         message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
633
634         /*
635          * register callback to handle updating printer data
636          * when a driver is initialized
637          */
638
639         message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
640
641         /* of course, none of the message callbacks matter if you don't
642            tell messages.c that you interested in receiving PRINT_GENERAL 
643            msgs.  This is done in claim_connection() */
644
645
646         if ( lp_security() == SEC_ADS ) {
647                 win_rc = check_published_printers();
648                 if (!W_ERROR_IS_OK(win_rc))
649                         DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
650         }
651
652         return True;
653 }
654
655 /*******************************************************************
656  Function to allow filename parsing "the old way".
657 ********************************************************************/
658
659 static BOOL driver_unix_convert(char *name,connection_struct *conn,
660                 char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
661 {
662         unix_format(name);
663         unix_clean_name(name);
664         trim_string(name,"/","/");
665         return unix_convert(name, conn, saved_last_component, bad_path, pst);
666 }
667
668 /*******************************************************************
669  tdb traversal function for counting printers.
670 ********************************************************************/
671
672 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
673                                       TDB_DATA data, void *context)
674 {
675         int *printer_count = (int*)context;
676  
677         if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
678                 (*printer_count)++;
679                 DEBUG(10,("traverse_counting_printers: printer = [%s]  printer_count = %d\n", key.dptr, *printer_count));
680         }
681  
682         return 0;
683 }
684  
685 /*******************************************************************
686  Update the spooler global c_setprinter. This variable is initialized
687  when the parent smbd starts with the number of existing printers. It
688  is monotonically increased by the current number of printers *after*
689  each add or delete printer RPC. Only Microsoft knows why... JRR020119
690 ********************************************************************/
691
692 uint32 update_c_setprinter(BOOL initialize)
693 {
694         int32 c_setprinter;
695         int32 printer_count = 0;
696  
697         tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
698  
699         /* Traverse the tdb, counting the printers */
700         tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
701  
702         /* If initializing, set c_setprinter to current printers count
703          * otherwise, bump it by the current printer count
704          */
705         if (!initialize)
706                 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
707         else
708                 c_setprinter = printer_count;
709  
710         DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
711         tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
712  
713         tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
714  
715         return (uint32)c_setprinter;
716 }
717
718 /*******************************************************************
719  Get the spooler global c_setprinter, accounting for initialization.
720 ********************************************************************/
721
722 uint32 get_c_setprinter(void)
723 {
724         int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
725  
726         if (c_setprinter == (int32)-1)
727                 c_setprinter = update_c_setprinter(True);
728  
729         DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
730  
731         return (uint32)c_setprinter;
732 }
733
734 /****************************************************************************
735  Get builtin form struct list.
736 ****************************************************************************/
737
738 int get_builtin_ntforms(nt_forms_struct **list)
739 {
740         *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
741         if (!*list) {
742                 return 0;
743         }
744         return sizeof(default_forms) / sizeof(default_forms[0]);
745 }
746
747 /****************************************************************************
748  get a builtin form struct
749 ****************************************************************************/
750
751 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
752 {
753         int i,count;
754         fstring form_name;
755         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
756         DEBUGADD(6,("Looking for builtin form %s \n", form_name));
757         count = sizeof(default_forms) / sizeof(default_forms[0]);
758         for (i=0;i<count;i++) {
759                 if (strequal(form_name,default_forms[i].name)) {
760                         DEBUGADD(6,("Found builtin form %s \n", form_name));
761                         memcpy(form,&default_forms[i],sizeof(*form));
762                         break;
763                 }
764         }
765
766         return (i !=count);
767 }
768
769 /****************************************************************************
770  get a form struct list.
771 ****************************************************************************/
772
773 int get_ntforms(nt_forms_struct **list)
774 {
775         TDB_DATA kbuf, newkey, dbuf;
776         nt_forms_struct form;
777         int ret;
778         int i;
779         int n = 0;
780
781         *list = NULL;
782
783         for (kbuf = tdb_firstkey(tdb_forms);
784              kbuf.dptr;
785              newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) 
786         {
787                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) 
788                         continue;
789                 
790                 dbuf = tdb_fetch(tdb_forms, kbuf);
791                 if (!dbuf.dptr) 
792                         continue;
793
794                 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
795                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
796                                  &i, &form.flag, &form.width, &form.length, &form.left,
797                                  &form.top, &form.right, &form.bottom);
798                 SAFE_FREE(dbuf.dptr);
799                 if (ret != dbuf.dsize) 
800                         continue;
801
802                 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
803                 if (!*list) {
804                         DEBUG(0,("get_ntforms: Realloc fail.\n"));
805                         return 0;
806                 }
807                 (*list)[n] = form;
808                 n++;
809         }
810         
811
812         return n;
813 }
814
815 /****************************************************************************
816 write a form struct list
817 ****************************************************************************/
818 int write_ntforms(nt_forms_struct **list, int number)
819 {
820         pstring buf, key;
821         int len;
822         TDB_DATA kbuf,dbuf;
823         int i;
824
825         for (i=0;i<number;i++) {
826                 /* save index, so list is rebuilt in correct order */
827                 len = tdb_pack(buf, sizeof(buf), "dddddddd",
828                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
829                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
830                                (*list)[i].bottom);
831                 if (len > sizeof(buf)) break;
832                 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
833                 kbuf.dsize = strlen(key)+1;
834                 kbuf.dptr = key;
835                 dbuf.dsize = len;
836                 dbuf.dptr = buf;
837                 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
838        }
839
840        return i;
841 }
842
843 /****************************************************************************
844 add a form struct at the end of the list
845 ****************************************************************************/
846 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
847 {
848         int n=0;
849         BOOL update;
850         fstring form_name;
851
852         /*
853          * NT tries to add forms even when
854          * they are already in the base
855          * only update the values if already present
856          */
857
858         update=False;
859         
860         unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
861         for (n=0; n<*count; n++) {
862                 if ( strequal((*list)[n].name, form_name) ) {
863                         update=True;
864                         break;
865                 }
866         }
867
868         if (update==False) {
869                 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
870                         DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
871                         return False;
872                 }
873                 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
874                 (*count)++;
875         }
876         
877         (*list)[n].flag=form->flags;
878         (*list)[n].width=form->size_x;
879         (*list)[n].length=form->size_y;
880         (*list)[n].left=form->left;
881         (*list)[n].top=form->top;
882         (*list)[n].right=form->right;
883         (*list)[n].bottom=form->bottom;
884
885         DEBUG(6,("add_a_form: Successfully %s form [%s]\n", 
886                 update ? "updated" : "added", form_name));
887
888         return True;
889 }
890
891 /****************************************************************************
892  Delete a named form struct.
893 ****************************************************************************/
894
895 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
896 {
897         pstring key;
898         TDB_DATA kbuf;
899         int n=0;
900         fstring form_name;
901
902         *ret = WERR_OK;
903
904         unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
905
906         for (n=0; n<*count; n++) {
907                 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
908                         DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
909                         break;
910                 }
911         }
912
913         if (n == *count) {
914                 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
915                 *ret = WERR_INVALID_PARAM;
916                 return False;
917         }
918
919         slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
920         kbuf.dsize = strlen(key)+1;
921         kbuf.dptr = key;
922         if (tdb_delete(tdb_forms, kbuf) != 0) {
923                 *ret = WERR_NOMEM;
924                 return False;
925         }
926
927         return True;
928 }
929
930 /****************************************************************************
931  Update a form struct.
932 ****************************************************************************/
933
934 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
935 {
936         int n=0;
937         fstring form_name;
938         unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
939
940         DEBUG(106, ("[%s]\n", form_name));
941         for (n=0; n<count; n++) {
942                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
943                 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
944                         break;
945         }
946
947         if (n==count) return;
948
949         (*list)[n].flag=form->flags;
950         (*list)[n].width=form->size_x;
951         (*list)[n].length=form->size_y;
952         (*list)[n].left=form->left;
953         (*list)[n].top=form->top;
954         (*list)[n].right=form->right;
955         (*list)[n].bottom=form->bottom;
956 }
957
958 /****************************************************************************
959  Get the nt drivers list.
960  Traverse the database and look-up the matching names.
961 ****************************************************************************/
962 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
963 {
964         int total=0;
965         const char *short_archi;
966         pstring key;
967         TDB_DATA kbuf, newkey;
968
969         short_archi = get_short_archi(architecture);
970         if (!short_archi) {
971                 return 0;
972         }
973
974         slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
975
976         for (kbuf = tdb_firstkey(tdb_drivers);
977              kbuf.dptr;
978              newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
979
980                 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
981                         continue;
982                 
983                 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
984                         DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
985                         return -1;
986                 }
987
988                 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
989                 total++;
990         }
991
992         return(total);
993 }
994
995 /****************************************************************************
996  Function to do the mapping between the long architecture name and
997  the short one.
998 ****************************************************************************/
999
1000 const char *get_short_archi(const char *long_archi)
1001 {
1002         int i=-1;
1003
1004         DEBUG(107,("Getting architecture dependant directory\n"));
1005         do {
1006                 i++;
1007         } while ( (archi_table[i].long_archi!=NULL ) &&
1008                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
1009
1010         if (archi_table[i].long_archi==NULL) {
1011                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1012                 return NULL;
1013         }
1014
1015         /* this might be client code - but shouldn't this be an fstrcpy etc? */
1016
1017         DEBUGADD(108,("index: [%d]\n", i));
1018         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1019         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1020
1021         return archi_table[i].short_archi;
1022 }
1023
1024 /****************************************************************************
1025  Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1026  There are two case to be covered here: PE (Portable Executable) and NE (New
1027  Executable) files. Both files support the same INFO structure, but PE files
1028  store the signature in unicode, and NE files store it as !unicode.
1029  returns -1 on error, 1 on version info found, and 0 on no version info found.
1030 ****************************************************************************/
1031
1032 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1033 {
1034         int     i;
1035         char    *buf = NULL;
1036         ssize_t byte_count;
1037
1038         if ((buf=SMB_MALLOC(PE_HEADER_SIZE)) == NULL) {
1039                 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
1040                                 fname, PE_HEADER_SIZE));
1041                 goto error_exit;
1042         }
1043
1044         /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
1045         if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1046                 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1047                          fname, (unsigned long)byte_count));
1048                 goto no_version_info;
1049         }
1050
1051         /* Is this really a DOS header? */
1052         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1053                 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1054                                 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1055                 goto no_version_info;
1056         }
1057
1058         /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1059         if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1060                 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1061                                 fname, errno));
1062                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1063                 goto no_version_info;
1064         }
1065
1066         if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
1067                 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1068                          fname, (unsigned long)byte_count));
1069                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1070                 goto no_version_info;
1071         }
1072
1073         /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1074         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1075                 unsigned int num_sections;
1076                 unsigned int section_table_bytes;
1077                 
1078                 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
1079                         DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
1080                                         fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
1081                         /* At this point, we assume the file is in error. It still could be somthing
1082                          * else besides a PE file, but it unlikely at this point.
1083                          */
1084                         goto error_exit;
1085                 }
1086
1087                 /* get the section table */
1088                 num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1089                 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1090                 if (section_table_bytes == 0)
1091                         goto error_exit;
1092
1093                 SAFE_FREE(buf);
1094                 if ((buf=SMB_MALLOC(section_table_bytes)) == NULL) {
1095                         DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1096                                         fname, section_table_bytes));
1097                         goto error_exit;
1098                 }
1099
1100                 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1101                         DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1102                                  fname, (unsigned long)byte_count));
1103                         goto error_exit;
1104                 }
1105
1106                 /* Iterate the section table looking for the resource section ".rsrc" */
1107                 for (i = 0; i < num_sections; i++) {
1108                         int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1109
1110                         if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1111                                 unsigned int section_pos   = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1112                                 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1113
1114                                 if (section_bytes == 0)
1115                                         goto error_exit;
1116
1117                                 SAFE_FREE(buf);
1118                                 if ((buf=SMB_MALLOC(section_bytes)) == NULL) {
1119                                         DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1120                                                         fname, section_bytes));
1121                                         goto error_exit;
1122                                 }
1123
1124                                 /* Seek to the start of the .rsrc section info */
1125                                 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1126                                         DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1127                                                         fname, errno));
1128                                         goto error_exit;
1129                                 }
1130
1131                                 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1132                                         DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1133                                                  fname, (unsigned long)byte_count));
1134                                         goto error_exit;
1135                                 }
1136
1137                                 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1138                                         goto error_exit;
1139
1140                                 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1141                                         /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1142                                         if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1143                                                 /* Align to next long address */
1144                                                 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1145
1146                                                 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1147                                                         *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1148                                                         *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1149                                                         
1150                                                         DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1151                                                                           fname, *major, *minor,
1152                                                                           (*major>>16)&0xffff, *major&0xffff,
1153                                                                           (*minor>>16)&0xffff, *minor&0xffff));
1154                                                         SAFE_FREE(buf);
1155                                                         return 1;
1156                                                 }
1157                                         }
1158                                 }
1159                         }
1160                 }
1161
1162                 /* Version info not found, fall back to origin date/time */
1163                 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1164                 SAFE_FREE(buf);
1165                 return 0;
1166
1167         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1168                 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1169                         DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1170                                         fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1171                         /* At this point, we assume the file is in error. It still could be somthing
1172                          * else besides a NE file, but it unlikely at this point. */
1173                         goto error_exit;
1174                 }
1175
1176                 /* Allocate a bit more space to speed up things */
1177                 SAFE_FREE(buf);
1178                 if ((buf=SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1179                         DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes  = %d\n",
1180                                         fname, PE_HEADER_SIZE));
1181                         goto error_exit;
1182                 }
1183
1184                 /* This is a HACK! I got tired of trying to sort through the messy
1185                  * 'NE' file format. If anyone wants to clean this up please have at
1186                  * it, but this works. 'NE' files will eventually fade away. JRR */
1187                 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1188                         /* Cover case that should not occur in a well formed 'NE' .dll file */
1189                         if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1190
1191                         for(i=0; i<byte_count; i++) {
1192                                 /* Fast skip past data that can't possibly match */
1193                                 if (buf[i] != 'V') continue;
1194
1195                                 /* Potential match data crosses buf boundry, move it to beginning
1196                                  * of buf, and fill the buf with as much as it will hold. */
1197                                 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1198                                         int bc;
1199
1200                                         memcpy(buf, &buf[i], byte_count-i);
1201                                         if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1202                                                                    (byte_count-i))) < 0) {
1203
1204                                                 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1205                                                                  fname, errno));
1206                                                 goto error_exit;
1207                                         }
1208
1209                                         byte_count = bc + (byte_count - i);
1210                                         if (byte_count<VS_VERSION_INFO_SIZE) break;
1211
1212                                         i = 0;
1213                                 }
1214
1215                                 /* Check that the full signature string and the magic number that
1216                                  * follows exist (not a perfect solution, but the chances that this
1217                                  * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1218                                  * twice, as it is simpler to read the code. */
1219                                 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1220                                         /* Compute skip alignment to next long address */
1221                                         int skip = -(SMB_VFS_LSEEK(fsp, fsp->fh->fd, 0, SEEK_CUR) - (byte_count - i) +
1222                                                                  sizeof(VS_SIGNATURE)) & 3;
1223                                         if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1224
1225                                         *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1226                                         *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1227                                         DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1228                                                           fname, *major, *minor,
1229                                                           (*major>>16)&0xffff, *major&0xffff,
1230                                                           (*minor>>16)&0xffff, *minor&0xffff));
1231                                         SAFE_FREE(buf);
1232                                         return 1;
1233                                 }
1234                         }
1235                 }
1236
1237                 /* Version info not found, fall back to origin date/time */
1238                 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1239                 SAFE_FREE(buf);
1240                 return 0;
1241
1242         } else
1243                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1244                 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1245                                 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1246
1247         no_version_info:
1248                 SAFE_FREE(buf);
1249                 return 0;
1250
1251         error_exit:
1252                 SAFE_FREE(buf);
1253                 return -1;
1254 }
1255
1256 /****************************************************************************
1257 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1258 share one or more files. During the MS installation process files are checked
1259 to insure that only a newer version of a shared file is installed over an
1260 older version. There are several possibilities for this comparison. If there
1261 is no previous version, the new one is newer (obviously). If either file is
1262 missing the version info structure, compare the creation date (on Unix use
1263 the modification date). Otherwise chose the numerically larger version number.
1264 ****************************************************************************/
1265
1266 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1267 {
1268         BOOL   use_version = True;
1269         pstring filepath;
1270
1271         uint32 new_major;
1272         uint32 new_minor;
1273         time_t new_create_time;
1274
1275         uint32 old_major;
1276         uint32 old_minor;
1277         time_t old_create_time;
1278
1279         files_struct    *fsp = NULL;
1280         SMB_STRUCT_STAT st;
1281         SMB_STRUCT_STAT stat_buf;
1282         BOOL bad_path;
1283
1284         SET_STAT_INVALID(st);
1285         SET_STAT_INVALID(stat_buf);
1286         new_create_time = (time_t)0;
1287         old_create_time = (time_t)0;
1288
1289         /* Get file version info (if available) for previous file (if it exists) */
1290         pstrcpy(filepath, old_file);
1291
1292         driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1293
1294         fsp = open_file_ntcreate(conn, filepath, &stat_buf,
1295                                 FILE_GENERIC_READ,
1296                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1297                                 FILE_OPEN,
1298                                 0,
1299                                 FILE_ATTRIBUTE_NORMAL,
1300                                 INTERNAL_OPEN_ONLY,
1301                                 NULL);
1302
1303         if (!fsp) {
1304                 /* Old file not found, so by definition new file is in fact newer */
1305                 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1306                                 filepath, errno));
1307                 return True;
1308
1309         } else {
1310                 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1311                 if (ret == -1) {
1312                         goto error_exit;
1313                 }
1314
1315                 if (!ret) {
1316                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1317                                          old_file));
1318                         use_version = False;
1319                         if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1320                         old_create_time = st.st_mtime;
1321                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1322                 }
1323         }
1324         close_file(fsp, NORMAL_CLOSE);
1325
1326         /* Get file version info (if available) for new file */
1327         pstrcpy(filepath, new_file);
1328         driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1329
1330         fsp = open_file_ntcreate(conn, filepath, &stat_buf,
1331                                 FILE_GENERIC_READ,
1332                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1333                                 FILE_OPEN,
1334                                 0,
1335                                 FILE_ATTRIBUTE_NORMAL,
1336                                 INTERNAL_OPEN_ONLY,
1337                                 NULL);
1338
1339         if (!fsp) {
1340                 /* New file not found, this shouldn't occur if the caller did its job */
1341                 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1342                                 filepath, errno));
1343                 goto error_exit;
1344
1345         } else {
1346                 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1347                 if (ret == -1) {
1348                         goto error_exit;
1349                 }
1350
1351                 if (!ret) {
1352                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1353                                          new_file));
1354                         use_version = False;
1355                         if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1356                         new_create_time = st.st_mtime;
1357                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1358                 }
1359         }
1360         close_file(fsp, NORMAL_CLOSE);
1361
1362         if (use_version && (new_major != old_major || new_minor != old_minor)) {
1363                 /* Compare versions and choose the larger version number */
1364                 if (new_major > old_major ||
1365                         (new_major == old_major && new_minor > old_minor)) {
1366                         
1367                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1368                         return True;
1369                 }
1370                 else {
1371                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1372                         return False;
1373                 }
1374
1375         } else {
1376                 /* Compare modification time/dates and choose the newest time/date */
1377                 if (new_create_time > old_create_time) {
1378                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1379                         return True;
1380                 }
1381                 else {
1382                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1383                         return False;
1384                 }
1385         }
1386
1387         error_exit:
1388                 if(fsp)
1389                         close_file(fsp, NORMAL_CLOSE);
1390                 return -1;
1391 }
1392
1393 /****************************************************************************
1394 Determine the correct cVersion associated with an architecture and driver
1395 ****************************************************************************/
1396 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1397                                    struct current_user *user, WERROR *perr)
1398 {
1399         int               cversion;
1400         NTSTATUS          nt_status;
1401         pstring           driverpath;
1402         DATA_BLOB         null_pw;
1403         fstring           res_type;
1404         files_struct      *fsp = NULL;
1405         BOOL              bad_path;
1406         SMB_STRUCT_STAT   st;
1407         connection_struct *conn;
1408
1409         SET_STAT_INVALID(st);
1410
1411         *perr = WERR_INVALID_PARAM;
1412
1413         /* If architecture is Windows 95/98/ME, the version is always 0. */
1414         if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1415                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1416                 *perr = WERR_OK;
1417                 return 0;
1418         }
1419
1420         /* If architecture is Windows x64, the version is always 3. */
1421         if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1422                 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1423                 *perr = WERR_OK;
1424                 return 3;
1425         }
1426
1427         /*
1428          * Connect to the print$ share under the same account as the user connected
1429          * to the rpc pipe. Note we must still be root to do this.
1430          */
1431
1432         /* Null password is ok - we are already an authenticated user... */
1433         null_pw = data_blob(NULL, 0);
1434         fstrcpy(res_type, "A:");
1435         become_root();
1436         conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1437         unbecome_root();
1438
1439         if (conn == NULL) {
1440                 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1441                 *perr = ntstatus_to_werror(nt_status);
1442                 return -1;
1443         }
1444
1445         /* We are temporarily becoming the connection user. */
1446         if (!become_user(conn, user->vuid)) {
1447                 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1448                 *perr = WERR_ACCESS_DENIED;
1449                 return -1;
1450         }
1451
1452         /* Open the driver file (Portable Executable format) and determine the
1453          * deriver the cversion. */
1454         slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1455
1456         driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
1457
1458         if ( !vfs_file_exist( conn, driverpath, &st ) ) {
1459                 *perr = WERR_BADFILE;
1460                 goto error_exit;
1461         }
1462
1463         fsp = open_file_ntcreate(conn, driverpath, &st,
1464                                 FILE_GENERIC_READ,
1465                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1466                                 FILE_OPEN,
1467                                 0,
1468                                 FILE_ATTRIBUTE_NORMAL,
1469                                 INTERNAL_OPEN_ONLY,
1470                                 NULL);
1471
1472         if (!fsp) {
1473                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1474                                 driverpath, errno));
1475                 *perr = WERR_ACCESS_DENIED;
1476                 goto error_exit;
1477         } else {
1478                 uint32 major;
1479                 uint32 minor;
1480                 int    ret = get_file_version(fsp, driverpath, &major, &minor);
1481                 if (ret == -1) goto error_exit;
1482
1483                 if (!ret) {
1484                         DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1485                         goto error_exit;
1486                 }
1487
1488                 /*
1489                  * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1490                  * for more details. Version in this case is not just the version of the 
1491                  * file, but the version in the sense of kernal mode (2) vs. user mode
1492                  * (3) drivers. Other bits of the version fields are the version info. 
1493                  * JRR 010716
1494                 */
1495                 cversion = major & 0x0000ffff;
1496                 switch (cversion) {
1497                         case 2: /* WinNT drivers */
1498                         case 3: /* Win2K drivers */
1499                                 break;
1500                         
1501                         default:
1502                                 DEBUG(6,("get_correct_cversion: cversion invalid [%s]  cversion = %d\n", 
1503                                         driverpath, cversion));
1504                                 goto error_exit;
1505                 }
1506
1507                 DEBUG(10,("get_correct_cversion: Version info found [%s]  major = 0x%x  minor = 0x%x\n",
1508                                   driverpath, major, minor));
1509         }
1510
1511         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1512                 driverpath, cversion));
1513
1514         close_file(fsp, NORMAL_CLOSE);
1515         close_cnum(conn, user->vuid);
1516         unbecome_user();
1517         *perr = WERR_OK;
1518         return cversion;
1519
1520
1521   error_exit:
1522
1523         if(fsp)
1524                 close_file(fsp, NORMAL_CLOSE);
1525
1526         close_cnum(conn, user->vuid);
1527         unbecome_user();
1528         return -1;
1529 }
1530
1531 /****************************************************************************
1532 ****************************************************************************/
1533 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1534                                                                                          struct current_user *user)
1535 {
1536         const char *architecture;
1537         fstring new_name;
1538         char *p;
1539         int i;
1540         WERROR err;
1541
1542         /* clean up the driver name.
1543          * we can get .\driver.dll
1544          * or worse c:\windows\system\driver.dll !
1545          */
1546         /* using an intermediate string to not have overlaping memcpy()'s */
1547         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1548                 fstrcpy(new_name, p+1);
1549                 fstrcpy(driver->driverpath, new_name);
1550         }
1551
1552         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1553                 fstrcpy(new_name, p+1);
1554                 fstrcpy(driver->datafile, new_name);
1555         }
1556
1557         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1558                 fstrcpy(new_name, p+1);
1559                 fstrcpy(driver->configfile, new_name);
1560         }
1561
1562         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1563                 fstrcpy(new_name, p+1);
1564                 fstrcpy(driver->helpfile, new_name);
1565         }
1566
1567         if (driver->dependentfiles) {
1568                 for (i=0; *driver->dependentfiles[i]; i++) {
1569                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1570                                 fstrcpy(new_name, p+1);
1571                                 fstrcpy(driver->dependentfiles[i], new_name);
1572                         }
1573                 }
1574         }
1575
1576         architecture = get_short_archi(driver->environment);
1577         if (!architecture) {
1578                 return WERR_UNKNOWN_PRINTER_DRIVER;
1579         }
1580         
1581         /* jfm:7/16/2000 the client always sends the cversion=0.
1582          * The server should check which version the driver is by reading
1583          * the PE header of driver->driverpath.
1584          *
1585          * For Windows 95/98 the version is 0 (so the value sent is correct)
1586          * For Windows NT (the architecture doesn't matter)
1587          *      NT 3.1: cversion=0
1588          *      NT 3.5/3.51: cversion=1
1589          *      NT 4: cversion=2
1590          *      NT2K: cversion=3
1591          */
1592         if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1593                 return err;
1594
1595         return WERR_OK;
1596 }
1597         
1598 /****************************************************************************
1599 ****************************************************************************/
1600 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1601 {
1602         const char *architecture;
1603         fstring new_name;
1604         char *p;
1605         int i;
1606         WERROR err;
1607
1608         /* clean up the driver name.
1609          * we can get .\driver.dll
1610          * or worse c:\windows\system\driver.dll !
1611          */
1612         /* using an intermediate string to not have overlaping memcpy()'s */
1613         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1614                 fstrcpy(new_name, p+1);
1615                 fstrcpy(driver->driverpath, new_name);
1616         }
1617
1618         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1619                 fstrcpy(new_name, p+1);
1620                 fstrcpy(driver->datafile, new_name);
1621         }
1622
1623         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1624                 fstrcpy(new_name, p+1);
1625                 fstrcpy(driver->configfile, new_name);
1626         }
1627
1628         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1629                 fstrcpy(new_name, p+1);
1630                 fstrcpy(driver->helpfile, new_name);
1631         }
1632
1633         if (driver->dependentfiles) {
1634                 for (i=0; *driver->dependentfiles[i]; i++) {
1635                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1636                                 fstrcpy(new_name, p+1);
1637                                 fstrcpy(driver->dependentfiles[i], new_name);
1638                         }
1639                 }
1640         }
1641
1642         architecture = get_short_archi(driver->environment);
1643         if (!architecture) {
1644                 return WERR_UNKNOWN_PRINTER_DRIVER;
1645         }
1646
1647         /* jfm:7/16/2000 the client always sends the cversion=0.
1648          * The server should check which version the driver is by reading
1649          * the PE header of driver->driverpath.
1650          *
1651          * For Windows 95/98 the version is 0 (so the value sent is correct)
1652          * For Windows NT (the architecture doesn't matter)
1653          *      NT 3.1: cversion=0
1654          *      NT 3.5/3.51: cversion=1
1655          *      NT 4: cversion=2
1656          *      NT2K: cversion=3
1657          */
1658
1659         if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1660                         return err;
1661
1662         return WERR_OK;
1663 }
1664
1665 /****************************************************************************
1666 ****************************************************************************/
1667 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1668                                                           uint32 level, struct current_user *user)
1669 {
1670         switch (level) {
1671                 case 3:
1672                 {
1673                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1674                         driver=driver_abstract.info_3;
1675                         return clean_up_driver_struct_level_3(driver, user);
1676                 }
1677                 case 6:
1678                 {
1679                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1680                         driver=driver_abstract.info_6;
1681                         return clean_up_driver_struct_level_6(driver, user);
1682                 }
1683                 default:
1684                         return WERR_INVALID_PARAM;
1685         }
1686 }
1687
1688 /****************************************************************************
1689  This function sucks and should be replaced. JRA.
1690 ****************************************************************************/
1691
1692 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1693 {
1694     dst->cversion  = src->version;
1695
1696     fstrcpy( dst->name, src->name);
1697     fstrcpy( dst->environment, src->environment);
1698     fstrcpy( dst->driverpath, src->driverpath);
1699     fstrcpy( dst->datafile, src->datafile);
1700     fstrcpy( dst->configfile, src->configfile);
1701     fstrcpy( dst->helpfile, src->helpfile);
1702     fstrcpy( dst->monitorname, src->monitorname);
1703     fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1704     dst->dependentfiles = src->dependentfiles;
1705 }
1706
1707 #if 0 /* Debugging function */
1708
1709 static char* ffmt(unsigned char *c){
1710         int i;
1711         static char ffmt_str[17];
1712
1713         for (i=0; i<16; i++) {
1714                 if ((c[i] < ' ') || (c[i] > '~'))
1715                         ffmt_str[i]='.';
1716                 else
1717                         ffmt_str[i]=c[i];
1718         }
1719     ffmt_str[16]='\0';
1720         return ffmt_str;
1721 }
1722
1723 #endif
1724
1725 /****************************************************************************
1726 ****************************************************************************/
1727 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, 
1728                                   struct current_user *user, WERROR *perr)
1729 {
1730         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1731         NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1732         const char *architecture;
1733         pstring new_dir;
1734         pstring old_name;
1735         pstring new_name;
1736         DATA_BLOB null_pw;
1737         connection_struct *conn;
1738         NTSTATUS nt_status;
1739         pstring inbuf;
1740         pstring outbuf;
1741         fstring res_type;
1742         BOOL bad_path;
1743         SMB_STRUCT_STAT st;
1744         int ver = 0;
1745         int i;
1746         int err;
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, &bad_path, &st);
1800         mkdir_internal(conn, new_dir, bad_path);
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, &bad_path, &st);
1826                         if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1827                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
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, &bad_path, &st);
1842                                 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1843                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
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, &bad_path, &st);
1860                                 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1861                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
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, &bad_path, &st);
1879                                 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1880                                                 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
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, &bad_path, &st);
1907                                         if ( !copy_file(new_name, old_name, conn,
1908                                                         OPENX_FILE_EXISTS_TRUNCATE|
1909                                                         OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
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 = 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 = 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 uuid 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 uuid));       
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         void *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 uuid 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(ads->ld, 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         void *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(NULL, NULL, 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 uuid *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 uuid))
3287                 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
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 uuid *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, sizeof(servername)-1 );
4372                         }
4373
4374                         result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4375         
4376                         
4377                         /* we have a new printer now.  Save it with this handle */
4378                         
4379                         if ( !W_ERROR_IS_OK(result) ) {
4380                                 TALLOC_FREE( *pp_printer );
4381                                 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", 
4382                                         sharename, (unsigned int)level, dos_errstr(result)));
4383                                 return result;
4384                         }
4385
4386                         dump_a_printer( *pp_printer, level);
4387                         
4388                         break;
4389                         
4390                 default:
4391                         TALLOC_FREE( *pp_printer );
4392                         return WERR_UNKNOWN_LEVEL;
4393         }
4394         
4395         return WERR_OK;
4396 }
4397
4398 /****************************************************************************
4399  Deletes a NT_PRINTER_INFO_LEVEL struct.
4400 ****************************************************************************/
4401
4402 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4403 {
4404         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4405
4406         if ( !printer )
4407                 return 0;
4408         
4409         switch (level) {
4410                 case 2:
4411                         if ( printer->info_2 ) 
4412                                 free_nt_printer_info_level_2(&printer->info_2);
4413                         break;
4414
4415                 default:
4416                         DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4417                         return 1;
4418         }
4419
4420         TALLOC_FREE(*pp_printer);
4421
4422         return 0;
4423 }
4424
4425 /****************************************************************************
4426 ****************************************************************************/
4427 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4428 {
4429         uint32 result;
4430         DEBUG(104,("adding a printer at level [%d]\n", level));
4431         dump_a_printer_driver(driver, level);
4432         
4433         switch (level) {
4434                 case 3:
4435                         result=add_a_printer_driver_3(driver.info_3);
4436                         break;
4437
4438                 case 6:
4439                         result=add_a_printer_driver_6(driver.info_6);
4440                         break;
4441
4442                 default:
4443                         result=1;
4444                         break;
4445         }
4446         
4447         return result;
4448 }
4449 /****************************************************************************
4450 ****************************************************************************/
4451
4452 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4453                             fstring drivername, const char *architecture, uint32 version)
4454 {
4455         WERROR result;
4456         
4457         switch (level) {
4458                 case 3:
4459                         /* Sometime we just want any version of the driver */
4460                         
4461                         if ( version == DRIVER_ANY_VERSION ) {
4462                                 /* look for Win2k first and then for NT4 */
4463                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4464                                                 architecture, 3);
4465                                                 
4466                                 if ( !W_ERROR_IS_OK(result) ) {
4467                                         result = get_a_printer_driver_3( &driver->info_3, 
4468                                                         drivername, architecture, 2 );
4469                                 }
4470                         } else {
4471                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
4472                                         architecture, version);                         
4473                         }
4474                         break;
4475                         
4476                 default:
4477                         result=W_ERROR(1);
4478                         break;
4479         }
4480         
4481         if (W_ERROR_IS_OK(result))
4482                 dump_a_printer_driver(*driver, level);
4483                 
4484         return result;
4485 }
4486
4487 /****************************************************************************
4488 ****************************************************************************/
4489 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4490 {
4491         uint32 result;
4492         
4493         switch (level) {
4494                 case 3:
4495                 {
4496                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4497                         if (driver.info_3 != NULL)
4498                         {
4499                                 info3=driver.info_3;
4500                                 SAFE_FREE(info3->dependentfiles);
4501                                 ZERO_STRUCTP(info3);
4502                                 SAFE_FREE(info3);
4503                                 result=0;
4504                         } else {
4505                                 result=4;
4506                         }
4507                         break;
4508                 }
4509                 case 6:
4510                 {
4511                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4512                         if (driver.info_6 != NULL) {
4513                                 info6=driver.info_6;
4514                                 SAFE_FREE(info6->dependentfiles);
4515                                 SAFE_FREE(info6->previousnames);
4516                                 ZERO_STRUCTP(info6);
4517                                 SAFE_FREE(info6);
4518                                 result=0;
4519                         } else {
4520                                 result=4;
4521                         }
4522                         break;
4523                 }
4524                 default:
4525                         result=1;
4526                         break;
4527         }
4528         return result;
4529 }
4530
4531
4532 /****************************************************************************
4533   Determine whether or not a particular driver is currently assigned
4534   to a printer
4535 ****************************************************************************/
4536
4537 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4538 {
4539         int snum;
4540         int n_services = lp_numservices();
4541         NT_PRINTER_INFO_LEVEL *printer = NULL;
4542         BOOL in_use = False;
4543
4544         if ( !info_3 ) 
4545                 return False;
4546
4547         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4548         
4549         /* loop through the printers.tdb and check for the drivername */
4550         
4551         for (snum=0; snum<n_services && !in_use; snum++) {
4552                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4553                         continue;
4554                 
4555                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4556                         continue;
4557                 
4558                 if ( strequal(info_3->name, printer->info_2->drivername) ) 
4559                         in_use = True;
4560                 
4561                 free_a_printer( &printer, 2 );
4562         }
4563         
4564         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4565         
4566         if ( in_use ) {
4567                 NT_PRINTER_DRIVER_INFO_LEVEL d;
4568                 WERROR werr;
4569                 
4570                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4571                 
4572                 /* we can still remove the driver if there is one of 
4573                    "Windows NT x86" version 2 or 3 left */
4574                    
4575                 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4576                         werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );                       
4577                 }
4578                 else {
4579                         switch ( info_3->cversion ) {
4580                         case 2:
4581                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4582                                 break;
4583                         case 3: 
4584                                 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4585                                 break;
4586                         default:
4587                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n", 
4588                                         info_3->cversion));
4589                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4590                                 break;
4591                         }
4592                 }
4593
4594                 /* now check the error code */
4595                                 
4596                 if ( W_ERROR_IS_OK(werr) ) {
4597                         /* it's ok to remove the driver, we have other architctures left */
4598                         in_use = False;
4599                         free_a_printer_driver( d, 3 );
4600                 }
4601         }
4602         
4603         /* report that the driver is not in use by default */
4604         
4605         return in_use;
4606 }
4607
4608
4609 /**********************************************************************
4610  Check to see if a ogiven file is in use by *info
4611  *********************************************************************/
4612  
4613 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4614 {
4615         int i = 0;
4616         
4617         if ( !info )
4618                 return False;
4619                 
4620         if ( strequal(file, info->driverpath) )
4621                 return True;
4622
4623         if ( strequal(file, info->datafile) )
4624                 return True;
4625
4626         if ( strequal(file, info->configfile) )
4627                 return True;
4628
4629         if ( strequal(file, info->helpfile) )
4630                 return True;
4631         
4632         /* see of there are any dependent files to examine */
4633         
4634         if ( !info->dependentfiles )
4635                 return False;
4636         
4637         while ( *info->dependentfiles[i] ) {
4638                 if ( strequal(file, info->dependentfiles[i]) )
4639                         return True;
4640                 i++;
4641         }
4642         
4643         return False;
4644
4645 }
4646
4647 /**********************************************************************
4648  Utility function to remove the dependent file pointed to by the 
4649  input parameter from the list 
4650  *********************************************************************/
4651
4652 static void trim_dependent_file( fstring files[], int idx )
4653 {
4654         
4655         /* bump everything down a slot */
4656
4657         while( *files[idx+1] ) {
4658                 fstrcpy( files[idx], files[idx+1] );
4659                 idx++;
4660         }
4661         
4662         *files[idx] = '\0';
4663
4664         return; 
4665 }
4666
4667 /**********************************************************************
4668  Check if any of the files used by src are also used by drv 
4669  *********************************************************************/
4670
4671 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, 
4672                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4673 {
4674         BOOL    in_use = False;
4675         int     i = 0;
4676         
4677         if ( !src || !drv )
4678                 return False;
4679                 
4680         /* check each file.  Remove it from the src structure if it overlaps */
4681         
4682         if ( drv_file_in_use(src->driverpath, drv) ) {
4683                 in_use = True;
4684                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4685                 fstrcpy( src->driverpath, "" );
4686         }
4687                 
4688         if ( drv_file_in_use(src->datafile, drv) ) {
4689                 in_use = True;
4690                 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4691                 fstrcpy( src->datafile, "" );
4692         }
4693                 
4694         if ( drv_file_in_use(src->configfile, drv) ) {
4695                 in_use = True;
4696                 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4697                 fstrcpy( src->configfile, "" );
4698         }
4699                 
4700         if ( drv_file_in_use(src->helpfile, drv) ) {
4701                 in_use = True;
4702                 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4703                 fstrcpy( src->helpfile, "" );
4704         }
4705         
4706         /* are there any dependentfiles to examine? */
4707         
4708         if ( !src->dependentfiles )
4709                 return in_use;
4710                 
4711         while ( *src->dependentfiles[i] ) {
4712                 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4713                         in_use = True;
4714                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4715                         trim_dependent_file( src->dependentfiles, i );
4716                 } else
4717                         i++;
4718         }               
4719                 
4720         return in_use;
4721 }
4722
4723 /****************************************************************************
4724   Determine whether or not a particular driver files are currently being 
4725   used by any other driver.  
4726   
4727   Return value is True if any files were in use by other drivers
4728   and False otherwise.
4729   
4730   Upon return, *info has been modified to only contain the driver files
4731   which are not in use
4732 ****************************************************************************/
4733
4734 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4735 {
4736         int                             i;
4737         int                             ndrivers;
4738         uint32                          version;
4739         fstring                         *list = NULL;
4740         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
4741         
4742         if ( !info )
4743                 return False;
4744         
4745         version = info->cversion;
4746         
4747         /* loop over all driver versions */
4748         
4749         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4750         
4751         /* get the list of drivers */
4752                 
4753         list = NULL;
4754         ndrivers = get_ntdrivers(&list, info->environment, version);
4755                 
4756         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
4757                 ndrivers, info->environment, version));
4758
4759         /* check each driver for overlap in files */
4760                 
4761         for (i=0; i<ndrivers; i++) {
4762                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4763                         
4764                 ZERO_STRUCT(driver);
4765                         
4766                 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4767                         SAFE_FREE(list);
4768                         return True;
4769                 }
4770                         
4771                 /* check if d2 uses any files from d1 */
4772                 /* only if this is a different driver than the one being deleted */
4773                         
4774                 if ( !strequal(info->name, driver.info_3->name) ) {
4775                         if ( trim_overlap_drv_files(info, driver.info_3) ) {
4776                                 free_a_printer_driver(driver, 3);
4777                                 SAFE_FREE( list );
4778                                 return True;
4779                         }
4780                 }
4781         
4782                 free_a_printer_driver(driver, 3);
4783         }       
4784         
4785         SAFE_FREE(list);
4786         
4787         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4788         
4789         driver.info_3 = info;
4790         
4791         if ( DEBUGLEVEL >= 20 )
4792                 dump_a_printer_driver( driver, 3 );
4793         
4794         return False;
4795 }
4796
4797 /****************************************************************************
4798   Actually delete the driver files.  Make sure that 
4799   printer_driver_files_in_use() return False before calling 
4800   this.
4801 ****************************************************************************/
4802
4803 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4804 {
4805         int i = 0;
4806         char *s;
4807         pstring file;
4808         connection_struct *conn;
4809         DATA_BLOB null_pw;
4810         NTSTATUS nt_status;
4811         fstring res_type;
4812         BOOL bad_path;
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, &bad_path, &st);
4856                         DEBUG(10,("deleting driverfile [%s]\n", s));
4857                         unlink_internals(conn, 0, file, 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, &bad_path, &st);
4865                         DEBUG(10,("deleting configfile [%s]\n", s));
4866                         unlink_internals(conn, 0, file, 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, &bad_path, &st);
4874                         DEBUG(10,("deleting datafile [%s]\n", s));
4875                         unlink_internals(conn, 0, file, 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, &bad_path, &st);
4883                         DEBUG(10,("deleting helpfile [%s]\n", s));
4884                         unlink_internals(conn, 0, file, 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, &bad_path, &st);
4899                                 DEBUG(10,("deleting dependent file [%s]\n", file));
4900                                 unlink_internals(conn, 0, file, 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->sec->owner_sid || !secdesc_ctr->sec->grp_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->sec->owner_sid ?
5011                         secdesc_ctr->sec->owner_sid :
5012                         old_secdesc_ctr->sec->owner_sid;
5013
5014                 group_sid = secdesc_ctr->sec->grp_sid ?
5015                         secdesc_ctr->sec->grp_sid :
5016                         old_secdesc_ctr->sec->grp_sid;
5017
5018                 dacl = secdesc_ctr->sec->dacl ?
5019                         secdesc_ctr->sec->dacl :
5020                         old_secdesc_ctr->sec->dacl;
5021
5022                 sacl = secdesc_ctr->sec->sacl ?
5023                         secdesc_ctr->sec->sacl :
5024                         old_secdesc_ctr->sec->sacl;
5025
5026                 /* Make a deep copy of the security descriptor */
5027
5028                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->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->sec) +
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)->sec) +
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)->sec->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)->sec->revision, (*secdesc_ctr)->sec->type,
5226                                             &owner_sid,
5227                                             (*secdesc_ctr)->sec->grp_sid,
5228                                             (*secdesc_ctr)->sec->sacl,
5229                                             (*secdesc_ctr)->sec->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)->sec->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->ace[i].trustee);
5262
5263                         DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5264                                    the_acl->ace[i].type, the_acl->ace[i].flags, 
5265                                    the_acl->ace[i].info.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->ace[i].info.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->sec, 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->sec);
5415
5416         result = se_access_check(secdesc->sec, 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(int snum)
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, lp_servicename(snum))))
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