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