one line merge from APP_HEAD
[tprouty/samba.git] / source / printing / nt_printing.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2000.
6  *  Copyright (C) Gerald Carter                     2002.
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 DOM_SID global_sid_World;
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  
42 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
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 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 static BOOL upgrade_to_version_3(void)
202 {
203         TDB_DATA kbuf, newkey, dbuf;
204  
205         DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
206  
207         for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
208                         newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
209
210                 dbuf = tdb_fetch(tdb_drivers, kbuf);
211
212                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
213                         DEBUG(0,("upgrade_to_version_3:moving form\n"));
214                         if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
215                                 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
216                                 return False;
217                         }
218                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
219                                 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
220                                 return False;
221                         }
222                 }
223  
224                 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
225                         DEBUG(0,("upgrade_to_version_3:moving printer\n"));
226                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
227                                 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
228                                 return False;
229                         }
230                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
231                                 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
232                                 return False;
233                         }
234                 }
235  
236                 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
237                         DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
238                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
239                                 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
240                                 return False;
241                         }
242                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
243                                 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
244                                 return False;
245                         }
246                 }
247  
248                 SAFE_FREE(dbuf.dptr);
249         }
250
251         return True;
252 }
253
254 /****************************************************************************
255  Open the NT printing tdb.
256 ****************************************************************************/
257
258 BOOL nt_printing_init(void)
259 {
260         static pid_t local_pid;
261         char *vstring = "INFO/version";
262
263         if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
264                 return True;
265  
266         tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
267         if (!tdb_drivers) {
268                 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
269                         lock_path("ntdrivers.tdb"), strerror(errno) ));
270                 return False;
271         }
272  
273         tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
274         if (!tdb_printers) {
275                 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
276                         lock_path("ntprinters.tdb"), strerror(errno) ));
277                 return False;
278         }
279  
280         tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
281         if (!tdb_forms) {
282                 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
283                         lock_path("ntforms.tdb"), strerror(errno) ));
284                 return False;
285         }
286  
287         local_pid = sys_getpid();
288  
289         /* handle a Samba upgrade */
290         tdb_lock_bystring(tdb_drivers, vstring);
291         {
292                 int32 vers_id;
293
294                 /* Cope with byte-reversed older versions of the db. */
295                 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
296                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
297                         /* Written on a bigendian machine with old fetch_int code. Save as le. */
298                         /* The only upgrade between V2 and V3 is to save the version in little-endian. */
299                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
300                         vers_id = NTDRIVERS_DATABASE_VERSION;
301                 }
302
303                 if (vers_id != NTDRIVERS_DATABASE_VERSION) {
304
305                         if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) { 
306                                 if (!upgrade_to_version_3())
307                                         return False;
308                         } else
309                                 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
310                          
311                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
312                 }
313         }
314         tdb_unlock_bystring(tdb_drivers, vstring);
315
316         update_c_setprinter(True);
317
318         /*
319          * register callback to handle updating printers as new
320          * drivers are installed
321          */
322
323         message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
324
325         /*
326          * register callback to handle updating printer data
327          * when a driver is initialized
328          */
329
330         message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
331
332
333         return True;
334 }
335
336 /*******************************************************************
337  tdb traversal function for counting printers.
338 ********************************************************************/
339
340 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
341                                       TDB_DATA data, void *context)
342 {
343         int *printer_count = (int*)context;
344  
345         if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
346                 (*printer_count)++;
347                 DEBUG(10,("traverse_counting_printers: printer = [%s]  printer_count = %d\n", key.dptr, *printer_count));
348         }
349  
350         return 0;
351 }
352  
353 /*******************************************************************
354  Update the spooler global c_setprinter. This variable is initialized
355  when the parent smbd starts with the number of existing printers. It
356  is monotonically increased by the current number of printers *after*
357  each add or delete printer RPC. Only Microsoft knows why... JRR020119
358 ********************************************************************/
359
360 uint32 update_c_setprinter(BOOL initialize)
361 {
362         int32 c_setprinter;
363         int32 printer_count = 0;
364  
365         tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
366  
367         /* Traverse the tdb, counting the printers */
368         tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
369  
370         /* If initializing, set c_setprinter to current printers count
371          * otherwise, bump it by the current printer count
372          */
373         if (!initialize)
374                 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
375         else
376                 c_setprinter = printer_count;
377  
378         DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
379         tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
380  
381         tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
382  
383         return (uint32)c_setprinter;
384 }
385
386 /*******************************************************************
387  Get the spooler global c_setprinter, accounting for initialization.
388 ********************************************************************/
389
390 uint32 get_c_setprinter(void)
391 {
392         int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
393  
394         if (c_setprinter == (int32)-1)
395                 c_setprinter = update_c_setprinter(True);
396  
397         DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
398  
399         return (uint32)c_setprinter;
400 }
401
402 /****************************************************************************
403  Get builtin form struct list.
404 ****************************************************************************/
405
406 int get_builtin_ntforms(nt_forms_struct **list)
407 {
408         *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
409         return sizeof(default_forms) / sizeof(default_forms[0]);
410 }
411
412 /****************************************************************************
413  get a builtin form struct
414 ****************************************************************************/
415
416 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
417 {
418         int i,count;
419         fstring form_name;
420         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
421         DEBUGADD(6,("Looking for builtin form %s \n", form_name));
422         count = sizeof(default_forms) / sizeof(default_forms[0]);
423         for (i=0;i<count;i++) {
424                 if (strequal(form_name,default_forms[i].name)) {
425                         DEBUGADD(6,("Found builtin form %s \n", form_name));
426                         memcpy(form,&default_forms[i],sizeof(*form));
427                         break;
428                 }
429         }
430
431         return (i !=count);
432 }
433
434 /****************************************************************************
435 get a form struct list
436 ****************************************************************************/
437 int get_ntforms(nt_forms_struct **list)
438 {
439         TDB_DATA kbuf, newkey, dbuf;
440         nt_forms_struct *tl;
441         nt_forms_struct form;
442         int ret;
443         int i;
444         int n = 0;
445
446         for (kbuf = tdb_firstkey(tdb_forms);
447              kbuf.dptr;
448              newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) 
449         {
450                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) 
451                         continue;
452                 
453                 dbuf = tdb_fetch(tdb_forms, kbuf);
454                 if (!dbuf.dptr) 
455                         continue;
456
457                 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
458                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
459                                  &i, &form.flag, &form.width, &form.length, &form.left,
460                                  &form.top, &form.right, &form.bottom);
461                 SAFE_FREE(dbuf.dptr);
462                 if (ret != dbuf.dsize) 
463                         continue;
464
465                 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
466                 if (!tl) {
467                         DEBUG(0,("get_ntforms: Realloc fail.\n"));
468                         return 0;
469                 }
470                 *list = tl;
471                 (*list)[n] = form;
472                 n++;
473         }
474         
475
476         return n;
477 }
478
479 /****************************************************************************
480 write a form struct list
481 ****************************************************************************/
482 int write_ntforms(nt_forms_struct **list, int number)
483 {
484         pstring buf, key;
485         int len;
486         TDB_DATA kbuf,dbuf;
487         int i;
488
489         for (i=0;i<number;i++) {
490                 /* save index, so list is rebuilt in correct order */
491                 len = tdb_pack(buf, sizeof(buf), "dddddddd",
492                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
493                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
494                                (*list)[i].bottom);
495                 if (len > sizeof(buf)) break;
496                 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
497                 kbuf.dsize = strlen(key)+1;
498                 kbuf.dptr = key;
499                 dbuf.dsize = len;
500                 dbuf.dptr = buf;
501                 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
502        }
503
504        return i;
505 }
506
507 /****************************************************************************
508 add a form struct at the end of the list
509 ****************************************************************************/
510 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
511 {
512         int n=0;
513         BOOL update;
514         fstring form_name;
515         nt_forms_struct *tl;
516
517         /*
518          * NT tries to add forms even when
519          * they are already in the base
520          * only update the values if already present
521          */
522
523         update=False;
524         
525         unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
526         for (n=0; n<*count; n++) {
527                 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
528                         DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
529                         update=True;
530                         break;
531                 }
532         }
533
534         if (update==False) {
535                 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
536                         DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
537                         return False;
538                 }
539                 *list = tl;
540                 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
541                 (*count)++;
542         }
543         
544         (*list)[n].flag=form->flags;
545         (*list)[n].width=form->size_x;
546         (*list)[n].length=form->size_y;
547         (*list)[n].left=form->left;
548         (*list)[n].top=form->top;
549         (*list)[n].right=form->right;
550         (*list)[n].bottom=form->bottom;
551
552         return True;
553 }
554
555 /****************************************************************************
556  delete a named form struct
557 ****************************************************************************/
558 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
559 {
560         pstring key;
561         TDB_DATA kbuf;
562         int n=0;
563         fstring form_name;
564
565         *ret = WERR_OK;
566
567         unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
568
569         for (n=0; n<*count; n++) {
570                 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
571                         DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
572                         break;
573                 }
574         }
575
576         if (n == *count) {
577                 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
578                 *ret = WERR_INVALID_PARAM;
579                 return False;
580         }
581
582         slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
583         kbuf.dsize = strlen(key)+1;
584         kbuf.dptr = key;
585         if (tdb_delete(tdb_forms, kbuf) != 0) {
586                 *ret = WERR_NOMEM;
587                 return False;
588         }
589
590         return True;
591 }
592
593 /****************************************************************************
594 update a form struct
595 ****************************************************************************/
596 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
597 {
598         int n=0;
599         fstring form_name;
600         unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
601
602         DEBUG(106, ("[%s]\n", form_name));
603         for (n=0; n<count; n++)
604         {
605                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
606                 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
607                         break;
608         }
609
610         if (n==count) return;
611
612         (*list)[n].flag=form->flags;
613         (*list)[n].width=form->size_x;
614         (*list)[n].length=form->size_y;
615         (*list)[n].left=form->left;
616         (*list)[n].top=form->top;
617         (*list)[n].right=form->right;
618         (*list)[n].bottom=form->bottom;
619 }
620
621 /****************************************************************************
622 get the nt drivers list
623
624 traverse the database and look-up the matching names
625 ****************************************************************************/
626 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
627 {
628         int total=0;
629         fstring short_archi;
630         fstring *fl;
631         pstring key;
632         TDB_DATA kbuf, newkey;
633
634         get_short_archi(short_archi, architecture);
635         slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
636
637         for (kbuf = tdb_firstkey(tdb_drivers);
638              kbuf.dptr;
639              newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
640                 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
641                 
642                 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
643                         DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
644                         return -1;
645                 }
646                 else *list = fl;
647
648                 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
649                 total++;
650         }
651
652         return(total);
653 }
654
655 /****************************************************************************
656 function to do the mapping between the long architecture name and
657 the short one.
658 ****************************************************************************/
659 BOOL get_short_archi(char *short_archi, char *long_archi)
660 {
661         struct table {
662                 char *long_archi;
663                 char *short_archi;
664         };
665         
666         struct table archi_table[]=
667         {
668                 {"Windows 4.0",          "WIN40"    },
669                 {"Windows NT x86",       "W32X86"   },
670                 {"Windows NT R4000",     "W32MIPS"  },
671                 {"Windows NT Alpha_AXP", "W32ALPHA" },
672                 {"Windows NT PowerPC",   "W32PPC"   },
673                 {NULL,                   ""         }
674         };
675         
676         int i=-1;
677
678         DEBUG(107,("Getting architecture dependant directory\n"));
679         do {
680                 i++;
681         } while ( (archi_table[i].long_archi!=NULL ) &&
682                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
683
684         if (archi_table[i].long_archi==NULL) {
685                 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
686                 return False;
687         }
688
689         StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
690
691         DEBUGADD(108,("index: [%d]\n", i));
692         DEBUGADD(108,("long architecture: [%s]\n", long_archi));
693         DEBUGADD(108,("short architecture: [%s]\n", short_archi));
694         
695         return True;
696 }
697
698 /****************************************************************************
699  Version information in Microsoft files is held in a VS_VERSION_INFO structure.
700  There are two case to be covered here: PE (Portable Executable) and NE (New
701  Executable) files. Both files support the same INFO structure, but PE files
702  store the signature in unicode, and NE files store it as !unicode.
703  returns -1 on error, 1 on version info found, and 0 on no version info found.
704 ****************************************************************************/
705
706 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
707 {
708         int     i;
709         char    *buf;
710         ssize_t byte_count;
711
712         if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
713                 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
714                                 fname, PE_HEADER_SIZE));
715                 goto error_exit;
716         }
717
718         /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
719         if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
720                 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
721                                 fname, byte_count));
722                 goto no_version_info;
723         }
724
725         /* Is this really a DOS header? */
726         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
727                 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
728                                 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
729                 goto no_version_info;
730         }
731
732         /* Skip OEM header (if any) and the DOS stub to start of Windows header */
733         if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
734                 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
735                                 fname, errno));
736                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
737                 goto no_version_info;
738         }
739
740         if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
741                 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
742                                 fname, byte_count));
743                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
744                 goto no_version_info;
745         }
746
747         /* The header may be a PE (Portable Executable) or an NE (New Executable) */
748         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
749                 int num_sections;
750                 int section_table_bytes;
751                 
752                 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
753                         DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
754                                         fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
755                         /* At this point, we assume the file is in error. It still could be somthing
756                          * else besides a PE file, but it unlikely at this point.
757                          */
758                         goto error_exit;
759                 }
760
761                 /* get the section table */
762                 num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
763                 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
764                 SAFE_FREE(buf);
765                 if ((buf=malloc(section_table_bytes)) == NULL) {
766                         DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
767                                         fname, section_table_bytes));
768                         goto error_exit;
769                 }
770
771                 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
772                         DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
773                                         fname, byte_count));
774                         goto error_exit;
775                 }
776
777                 /* Iterate the section table looking for the resource section ".rsrc" */
778                 for (i = 0; i < num_sections; i++) {
779                         int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
780
781                         if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
782                                 int section_pos   = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
783                                 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
784
785                                 SAFE_FREE(buf);
786                                 if ((buf=malloc(section_bytes)) == NULL) {
787                                         DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
788                                                         fname, section_bytes));
789                                         goto error_exit;
790                                 }
791
792                                 /* Seek to the start of the .rsrc section info */
793                                 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
794                                         DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
795                                                         fname, errno));
796                                         goto error_exit;
797                                 }
798
799                                 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
800                                         DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
801                                                         fname, byte_count));
802                                         goto error_exit;
803                                 }
804
805                                 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
806                                         /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
807                                         if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
808                                                 /* Align to next long address */
809                                                 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
810
811                                                 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
812                                                         *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
813                                                         *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
814                                                         
815                                                         DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
816                                                                           fname, *major, *minor,
817                                                                           (*major>>16)&0xffff, *major&0xffff,
818                                                                           (*minor>>16)&0xffff, *minor&0xffff));
819                                                         SAFE_FREE(buf);
820                                                         return 1;
821                                                 }
822                                         }
823                                 }
824                         }
825                 }
826
827                 /* Version info not found, fall back to origin date/time */
828                 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
829                 SAFE_FREE(buf);
830                 return 0;
831
832         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
833                 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
834                         DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
835                                         fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
836                         /* At this point, we assume the file is in error. It still could be somthing
837                          * else besides a NE file, but it unlikely at this point. */
838                         goto error_exit;
839                 }
840
841                 /* Allocate a bit more space to speed up things */
842                 SAFE_FREE(buf);
843                 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
844                         DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes  = %d\n",
845                                         fname, PE_HEADER_SIZE));
846                         goto error_exit;
847                 }
848
849                 /* This is a HACK! I got tired of trying to sort through the messy
850                  * 'NE' file format. If anyone wants to clean this up please have at
851                  * it, but this works. 'NE' files will eventually fade away. JRR */
852                 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
853                         /* Cover case that should not occur in a well formed 'NE' .dll file */
854                         if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
855
856                         for(i=0; i<byte_count; i++) {
857                                 /* Fast skip past data that can't possibly match */
858                                 if (buf[i] != 'V') continue;
859
860                                 /* Potential match data crosses buf boundry, move it to beginning
861                                  * of buf, and fill the buf with as much as it will hold. */
862                                 if (i>byte_count-VS_VERSION_INFO_SIZE) {
863                                         int bc;
864
865                                         memcpy(buf, &buf[i], byte_count-i);
866                                         if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
867                                                                    (byte_count-i))) < 0) {
868
869                                                 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
870                                                                  fname, errno));
871                                                 goto error_exit;
872                                         }
873
874                                         byte_count = bc + (byte_count - i);
875                                         if (byte_count<VS_VERSION_INFO_SIZE) break;
876
877                                         i = 0;
878                                 }
879
880                                 /* Check that the full signature string and the magic number that
881                                  * follows exist (not a perfect solution, but the chances that this
882                                  * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
883                                  * twice, as it is simpler to read the code. */
884                                 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
885                                         /* Compute skip alignment to next long address */
886                                         int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
887                                                                  sizeof(VS_SIGNATURE)) & 3;
888                                         if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
889
890                                         *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
891                                         *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
892                                         DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
893                                                           fname, *major, *minor,
894                                                           (*major>>16)&0xffff, *major&0xffff,
895                                                           (*minor>>16)&0xffff, *minor&0xffff));
896                                         SAFE_FREE(buf);
897                                         return 1;
898                                 }
899                         }
900                 }
901
902                 /* Version info not found, fall back to origin date/time */
903                 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
904                 SAFE_FREE(buf);
905                 return 0;
906
907         } else
908                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
909                 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
910                                 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
911
912         no_version_info:
913                 SAFE_FREE(buf);
914                 return 0;
915
916         error_exit:
917                 SAFE_FREE(buf);
918                 return -1;
919 }
920
921 /****************************************************************************
922 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
923 share one or more files. During the MS installation process files are checked
924 to insure that only a newer version of a shared file is installed over an
925 older version. There are several possibilities for this comparison. If there
926 is no previous version, the new one is newer (obviously). If either file is
927 missing the version info structure, compare the creation date (on Unix use
928 the modification date). Otherwise chose the numerically larger version number.
929 ****************************************************************************/
930 static int file_version_is_newer(connection_struct *conn, fstring new_file,
931                                                                 fstring old_file)
932 {
933         BOOL   use_version = True;
934         pstring filepath;
935
936         uint32 new_major;
937         uint32 new_minor;
938         time_t new_create_time;
939
940         uint32 old_major;
941         uint32 old_minor;
942         time_t old_create_time;
943
944         int access_mode;
945         int action;
946         files_struct    *fsp = NULL;
947         SMB_STRUCT_STAT st;
948         SMB_STRUCT_STAT stat_buf;
949         BOOL bad_path;
950
951         ZERO_STRUCT(st);
952         ZERO_STRUCT(stat_buf);
953         new_create_time = (time_t)0;
954         old_create_time = (time_t)0;
955
956         /* Get file version info (if available) for previous file (if it exists) */
957         pstrcpy(filepath, old_file);
958
959         unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
960
961         fsp = open_file_shared(conn, filepath, &stat_buf,
962                                                    SET_OPEN_MODE(DOS_OPEN_RDONLY),
963                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
964                                                    0, 0, &access_mode, &action);
965         if (!fsp) {
966                 /* Old file not found, so by definition new file is in fact newer */
967                 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
968                                 filepath, errno));
969                 return True;
970
971         } else {
972                 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
973                 if (ret == -1) goto error_exit;
974
975                 if (!ret) {
976                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
977                                          old_file));
978                         use_version = False;
979                         if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
980                         old_create_time = st.st_mtime;
981                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
982                 }
983         }
984         close_file(fsp, True);
985
986         /* Get file version info (if available) for new file */
987         pstrcpy(filepath, new_file);
988         unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
989
990         fsp = open_file_shared(conn, filepath, &stat_buf,
991                                                    SET_OPEN_MODE(DOS_OPEN_RDONLY),
992                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
993                                                    0, 0, &access_mode, &action);
994         if (!fsp) {
995                 /* New file not found, this shouldn't occur if the caller did its job */
996                 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
997                                 filepath, errno));
998                 goto error_exit;
999
1000         } else {
1001                 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1002                 if (ret == -1) goto error_exit;
1003
1004                 if (!ret) {
1005                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1006                                          new_file));
1007                         use_version = False;
1008                         if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1009                         new_create_time = st.st_mtime;
1010                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1011                 }
1012         }
1013         close_file(fsp, True);
1014
1015         if (use_version && (new_major != old_major || new_minor != old_minor)) {
1016                 /* Compare versions and choose the larger version number */
1017                 if (new_major > old_major ||
1018                         (new_major == old_major && new_minor > old_minor)) {
1019                         
1020                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1021                         return True;
1022                 }
1023                 else {
1024                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1025                         return False;
1026                 }
1027
1028         } else {
1029                 /* Compare modification time/dates and choose the newest time/date */
1030                 if (new_create_time > old_create_time) {
1031                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1032                         return True;
1033                 }
1034                 else {
1035                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1036                         return False;
1037                 }
1038         }
1039
1040         error_exit:
1041                 if(fsp)
1042                         close_file(fsp, True);
1043                 return -1;
1044 }
1045
1046 /****************************************************************************
1047 Determine the correct cVersion associated with an architecture and driver
1048 ****************************************************************************/
1049 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
1050                                    struct current_user *user, WERROR *perr)
1051 {
1052         int               cversion;
1053         int               access_mode;
1054         int               action;
1055         NTSTATUS          nt_status;
1056         pstring           driverpath;
1057         DATA_BLOB         null_pw;
1058         files_struct      *fsp = NULL;
1059         BOOL              bad_path;
1060         SMB_STRUCT_STAT   st;
1061         connection_struct *conn;
1062
1063         ZERO_STRUCT(st);
1064
1065         *perr = WERR_INVALID_PARAM;
1066
1067         /* If architecture is Windows 95/98/ME, the version is always 0. */
1068         if (strcmp(architecture, "WIN40") == 0) {
1069                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1070                 *perr = WERR_OK;
1071                 return 0;
1072         }
1073
1074         /*
1075          * Connect to the print$ share under the same account as the user connected
1076          * to the rpc pipe. Note we must still be root to do this.
1077          */
1078
1079         /* Null password is ok - we are already an authenticated user... */
1080         null_pw = data_blob(NULL, 0);
1081         become_root();
1082         conn = make_connection_with_chdir("print$", null_pw, "A:", user->vuid, &nt_status);
1083         unbecome_root();
1084
1085         if (conn == NULL) {
1086                 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1087                 *perr = ntstatus_to_werror(nt_status);
1088                 return -1;
1089         }
1090
1091         /* We are temporarily becoming the connection user. */
1092         if (!become_user(conn, conn->vuid)) {
1093                 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1094                 *perr = WERR_ACCESS_DENIED;
1095                 return -1;
1096         }
1097
1098         /* Open the driver file (Portable Executable format) and determine the
1099          * deriver the cversion. */
1100         slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1101
1102         unix_convert(driverpath,conn,NULL,&bad_path,&st);
1103
1104         fsp = open_file_shared(conn, driverpath, &st,
1105                                                    SET_OPEN_MODE(DOS_OPEN_RDONLY),
1106                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1107                                                    0, 0, &access_mode, &action);
1108         if (!fsp) {
1109                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1110                                 driverpath, errno));
1111                 *perr = WERR_ACCESS_DENIED;
1112                 goto error_exit;
1113         }
1114         else {
1115                 uint32 major;
1116                 uint32 minor;
1117                 int    ret = get_file_version(fsp, driverpath, &major, &minor);
1118                 if (ret == -1) goto error_exit;
1119
1120                 if (!ret) {
1121                         DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1122                         goto error_exit;
1123                 }
1124
1125                 /*
1126                  * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1127                  * for more details. Version in this case is not just the version of the 
1128                  * file, but the version in the sense of kernal mode (2) vs. user mode
1129                  * (3) drivers. Other bits of the version fields are the version info. 
1130                  * JRR 010716
1131                 */
1132                 cversion = major & 0x0000ffff;
1133                 switch (cversion) {
1134                         case 2: /* WinNT drivers */
1135                         case 3: /* Win2K drivers */
1136                                 break;
1137                         
1138                         default:
1139                                 DEBUG(6,("get_correct_cversion: cversion invalid [%s]  cversion = %d\n", 
1140                                         driverpath, cversion));
1141                                 goto error_exit;
1142                 }
1143
1144                 DEBUG(10,("get_correct_cversion: Version info found [%s]  major = 0x%x  minor = 0x%x\n",
1145                                   driverpath, major, minor));
1146         }
1147
1148     DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1149                         driverpath, cversion));
1150
1151         close_file(fsp, True);
1152         close_cnum(conn, user->vuid);
1153         unbecome_user();
1154         *perr = WERR_OK;
1155         return cversion;
1156
1157
1158   error_exit:
1159
1160         if(fsp)
1161                 close_file(fsp, True);
1162
1163         close_cnum(conn, user->vuid);
1164         unbecome_user();
1165         return -1;
1166 }
1167
1168 /****************************************************************************
1169 ****************************************************************************/
1170 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1171                                                                                          struct current_user *user)
1172 {
1173         fstring architecture;
1174         fstring new_name;
1175         char *p;
1176         int i;
1177         WERROR err;
1178
1179         /* clean up the driver name.
1180          * we can get .\driver.dll
1181          * or worse c:\windows\system\driver.dll !
1182          */
1183         /* using an intermediate string to not have overlaping memcpy()'s */
1184         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1185                 fstrcpy(new_name, p+1);
1186                 fstrcpy(driver->driverpath, new_name);
1187         }
1188
1189         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1190                 fstrcpy(new_name, p+1);
1191                 fstrcpy(driver->datafile, new_name);
1192         }
1193
1194         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1195                 fstrcpy(new_name, p+1);
1196                 fstrcpy(driver->configfile, new_name);
1197         }
1198
1199         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1200                 fstrcpy(new_name, p+1);
1201                 fstrcpy(driver->helpfile, new_name);
1202         }
1203
1204         if (driver->dependentfiles) {
1205                 for (i=0; *driver->dependentfiles[i]; i++) {
1206                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1207                                 fstrcpy(new_name, p+1);
1208                                 fstrcpy(driver->dependentfiles[i], new_name);
1209                         }
1210                 }
1211         }
1212
1213         get_short_archi(architecture, driver->environment);
1214         
1215         /* jfm:7/16/2000 the client always sends the cversion=0.
1216          * The server should check which version the driver is by reading
1217          * the PE header of driver->driverpath.
1218          *
1219          * For Windows 95/98 the version is 0 (so the value sent is correct)
1220          * For Windows NT (the architecture doesn't matter)
1221          *      NT 3.1: cversion=0
1222          *      NT 3.5/3.51: cversion=1
1223          *      NT 4: cversion=2
1224          *      NT2K: cversion=3
1225          */
1226         if ((driver->cversion = get_correct_cversion( architecture,
1227                                                                         driver->driverpath, user, &err)) == -1)
1228                 return err;
1229
1230         return WERR_OK;
1231 }
1232         
1233 /****************************************************************************
1234 ****************************************************************************/
1235 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1236 {
1237         fstring architecture;
1238         fstring new_name;
1239         char *p;
1240         int i;
1241         WERROR err;
1242
1243         /* clean up the driver name.
1244          * we can get .\driver.dll
1245          * or worse c:\windows\system\driver.dll !
1246          */
1247         /* using an intermediate string to not have overlaping memcpy()'s */
1248         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1249                 fstrcpy(new_name, p+1);
1250                 fstrcpy(driver->driverpath, new_name);
1251         }
1252
1253         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1254                 fstrcpy(new_name, p+1);
1255                 fstrcpy(driver->datafile, new_name);
1256         }
1257
1258         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1259                 fstrcpy(new_name, p+1);
1260                 fstrcpy(driver->configfile, new_name);
1261         }
1262
1263         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1264                 fstrcpy(new_name, p+1);
1265                 fstrcpy(driver->helpfile, new_name);
1266         }
1267
1268         if (driver->dependentfiles) {
1269                 for (i=0; *driver->dependentfiles[i]; i++) {
1270                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1271                                 fstrcpy(new_name, p+1);
1272                                 fstrcpy(driver->dependentfiles[i], new_name);
1273                         }
1274                 }
1275         }
1276
1277         get_short_archi(architecture, driver->environment);
1278
1279         /* jfm:7/16/2000 the client always sends the cversion=0.
1280          * The server should check which version the driver is by reading
1281          * the PE header of driver->driverpath.
1282          *
1283          * For Windows 95/98 the version is 0 (so the value sent is correct)
1284          * For Windows NT (the architecture doesn't matter)
1285          *      NT 3.1: cversion=0
1286          *      NT 3.5/3.51: cversion=1
1287          *      NT 4: cversion=2
1288          *      NT2K: cversion=3
1289          */
1290         if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1291                 return err;
1292
1293         return WERR_OK;
1294 }
1295
1296 /****************************************************************************
1297 ****************************************************************************/
1298 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1299                                                           uint32 level, struct current_user *user)
1300 {
1301         switch (level) {
1302                 case 3:
1303                 {
1304                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1305                         driver=driver_abstract.info_3;
1306                         return clean_up_driver_struct_level_3(driver, user);
1307                 }
1308                 case 6:
1309                 {
1310                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1311                         driver=driver_abstract.info_6;
1312                         return clean_up_driver_struct_level_6(driver, user);
1313                 }
1314                 default:
1315                         return WERR_INVALID_PARAM;
1316         }
1317 }
1318
1319 /****************************************************************************
1320  This function sucks and should be replaced. JRA.
1321 ****************************************************************************/
1322
1323 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1324 {
1325     dst->cversion  = src->version;
1326
1327     fstrcpy( dst->name, src->name);
1328     fstrcpy( dst->environment, src->environment);
1329     fstrcpy( dst->driverpath, src->driverpath);
1330     fstrcpy( dst->datafile, src->datafile);
1331     fstrcpy( dst->configfile, src->configfile);
1332     fstrcpy( dst->helpfile, src->helpfile);
1333     fstrcpy( dst->monitorname, src->monitorname);
1334     fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1335     dst->dependentfiles = src->dependentfiles;
1336 }
1337
1338 #if 0 /* Debugging function */
1339
1340 static char* ffmt(unsigned char *c){
1341         int i;
1342         static char ffmt_str[17];
1343
1344         for (i=0; i<16; i++) {
1345                 if ((c[i] < ' ') || (c[i] > '~'))
1346                         ffmt_str[i]='.';
1347                 else
1348                         ffmt_str[i]=c[i];
1349         }
1350     ffmt_str[16]='\0';
1351         return ffmt_str;
1352 }
1353
1354 #endif
1355
1356 /****************************************************************************
1357 ****************************************************************************/
1358 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, 
1359                                   struct current_user *user, WERROR *perr)
1360 {
1361         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1362         NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1363         fstring architecture;
1364         pstring new_dir;
1365         pstring old_name;
1366         pstring new_name;
1367         DATA_BLOB null_pw;
1368         connection_struct *conn;
1369         NTSTATUS nt_status;
1370         pstring inbuf;
1371         pstring outbuf;
1372         int ver = 0;
1373         int i;
1374
1375         memset(inbuf, '\0', sizeof(inbuf));
1376         memset(outbuf, '\0', sizeof(outbuf));
1377         *perr = WERR_OK;
1378
1379         if (level==3)
1380                 driver=driver_abstract.info_3;
1381         else if (level==6) {
1382                 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1383                 driver = &converted_driver;
1384         } else {
1385                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1386                 return False;
1387         }
1388
1389         get_short_archi(architecture, driver->environment);
1390
1391         /*
1392          * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1393          * Note we must be root to do this.
1394          */
1395
1396         become_root();
1397         null_pw = data_blob(NULL, 0);
1398         conn = make_connection_with_chdir("print$", null_pw, "A:", user->vuid, &nt_status);
1399         unbecome_root();
1400
1401         if (conn == NULL) {
1402                 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1403                 *perr = ntstatus_to_werror(nt_status);
1404                 return False;
1405         }
1406
1407         /*
1408          * Save who we are - we are temporarily becoming the connection user.
1409          */
1410
1411         if (!become_user(conn, conn->vuid)) {
1412                 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1413                 return False;
1414         }
1415
1416         /*
1417          * make the directories version and version\driver_name
1418          * under the architecture directory.
1419          */
1420         DEBUG(5,("Creating first directory\n"));
1421         slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1422         mkdir_internal(conn, new_dir);
1423
1424         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1425          * listed for this driver which has already been moved, skip it (note:
1426          * drivers may list the same file name several times. Then check if the
1427          * file already exists in archi\cversion\, if so, check that the version
1428          * info (or time stamps if version info is unavailable) is newer (or the
1429          * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1430          * Otherwise, delete the file.
1431          *
1432          * If a file is not moved to archi\cversion\ because of an error, all the
1433          * rest of the 'unmoved' driver files are removed from archi\. If one or
1434          * more of the driver's files was already moved to archi\cversion\, it
1435          * potentially leaves the driver in a partially updated state. Version
1436          * trauma will most likely occur if an client attempts to use any printer
1437          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1438          * done is appropriate... later JRR
1439          */
1440
1441         DEBUG(5,("Moving files now !\n"));
1442
1443         if (driver->driverpath && strlen(driver->driverpath)) {
1444                 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);      
1445                 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);   
1446                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1447                         NTSTATUS status;
1448                         status = rename_internals(conn, new_name, old_name, True);
1449                         if (!NT_STATUS_IS_OK(status)) {
1450                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1451                                                 new_name, old_name));
1452                                 *perr = ntstatus_to_werror(status);
1453                                 unlink_internals(conn, 0, new_name);
1454                                 ver = -1;
1455                         }
1456                 }
1457                 else
1458                         unlink_internals(conn, 0, new_name);
1459         }
1460
1461         if (driver->datafile && strlen(driver->datafile)) {
1462                 if (!strequal(driver->datafile, driver->driverpath)) {
1463                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);        
1464                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);     
1465                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1466                                 NTSTATUS status;
1467                                 status = rename_internals(conn, new_name, old_name, True);
1468                                 if (!NT_STATUS_IS_OK(status)) {
1469                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1470                                                         new_name, old_name));
1471                                         *perr = ntstatus_to_werror(status);
1472                                         unlink_internals(conn, 0, new_name);
1473                                         ver = -1;
1474                                 }
1475                         }
1476                         else
1477                                 unlink_internals(conn, 0, new_name);
1478                 }
1479         }
1480
1481         if (driver->configfile && strlen(driver->configfile)) {
1482                 if (!strequal(driver->configfile, driver->driverpath) &&
1483                         !strequal(driver->configfile, driver->datafile)) {
1484                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);      
1485                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);   
1486                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1487                                 NTSTATUS status;
1488                                 status = rename_internals(conn, new_name, old_name, True);
1489                                 if (!NT_STATUS_IS_OK(status)) {
1490                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1491                                                         new_name, old_name));
1492                                         *perr = ntstatus_to_werror(status);
1493                                         unlink_internals(conn, 0, new_name);
1494                                         ver = -1;
1495                                 }
1496                         }
1497                         else
1498                                 unlink_internals(conn, 0, new_name);
1499                 }
1500         }
1501
1502         if (driver->helpfile && strlen(driver->helpfile)) {
1503                 if (!strequal(driver->helpfile, driver->driverpath) &&
1504                         !strequal(driver->helpfile, driver->datafile) &&
1505                         !strequal(driver->helpfile, driver->configfile)) {
1506                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);        
1507                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);     
1508                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1509                                 NTSTATUS status;
1510                                 status = rename_internals(conn, new_name, old_name, True);
1511                                 if (!NT_STATUS_IS_OK(status)) {
1512                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1513                                                         new_name, old_name));
1514                                         *perr = ntstatus_to_werror(status);
1515                                         unlink_internals(conn, 0, new_name);
1516                                         ver = -1;
1517                                 }
1518                         }
1519                         else
1520                                 unlink_internals(conn, 0, new_name);
1521                 }
1522         }
1523
1524         if (driver->dependentfiles) {
1525                 for (i=0; *driver->dependentfiles[i]; i++) {
1526                         if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1527                                 !strequal(driver->dependentfiles[i], driver->datafile) &&
1528                                 !strequal(driver->dependentfiles[i], driver->configfile) &&
1529                                 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1530                                 int j;
1531                                 for (j=0; j < i; j++) {
1532                                         if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1533                                                 goto NextDriver;
1534                                         }
1535                                 }
1536
1537                                 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);       
1538                                 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);    
1539                                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1540                                         NTSTATUS status;
1541                                         status = rename_internals(conn, new_name, old_name, True);
1542                                         if (!NT_STATUS_IS_OK(status)) {
1543                                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1544                                                                 new_name, old_name));
1545                                                 *perr = ntstatus_to_werror(status);
1546                                                 unlink_internals(conn, 0, new_name);
1547                                                 ver = -1;
1548                                         }
1549                                 }
1550                                 else
1551                                         unlink_internals(conn, 0, new_name);
1552                         }
1553                 NextDriver: ;
1554                 }
1555         }
1556
1557         close_cnum(conn, user->vuid);
1558         unbecome_user();
1559
1560         return ver == -1 ? False : True;
1561 }
1562
1563 /****************************************************************************
1564 ****************************************************************************/
1565 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1566 {
1567         int len, buflen;
1568         fstring architecture;
1569         pstring directory;
1570         pstring temp_name;
1571         pstring key;
1572         char *buf;
1573         int i, ret;
1574         TDB_DATA kbuf, dbuf;
1575
1576         get_short_archi(architecture, driver->environment);
1577
1578         /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1579          * \\server is added in the rpc server layer.
1580          * It does make sense to NOT store the server's name in the printer TDB.
1581          */
1582
1583         slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1584
1585         /* .inf files do not always list a file for each of the four standard files. 
1586          * Don't prepend a path to a null filename, or client claims:
1587          *   "The server on which the printer resides does not have a suitable 
1588          *   <printer driver name> printer driver installed. Click OK if you 
1589          *   wish to install the driver on your local machine."
1590          */
1591         if (strlen(driver->driverpath)) {
1592                 fstrcpy(temp_name, driver->driverpath);
1593                 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1594         }
1595
1596         if (strlen(driver->datafile)) {
1597                 fstrcpy(temp_name, driver->datafile);
1598                 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1599         }
1600
1601         if (strlen(driver->configfile)) {
1602                 fstrcpy(temp_name, driver->configfile);
1603                 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1604         }
1605
1606         if (strlen(driver->helpfile)) {
1607                 fstrcpy(temp_name, driver->helpfile);
1608                 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1609         }
1610
1611         if (driver->dependentfiles) {
1612                 for (i=0; *driver->dependentfiles[i]; i++) {
1613                         fstrcpy(temp_name, driver->dependentfiles[i]);
1614                         slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1615                 }
1616         }
1617
1618         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1619
1620         DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1621
1622         buf = NULL;
1623         len = buflen = 0;
1624
1625  again:
1626         len = 0;
1627         len += tdb_pack(buf+len, buflen-len, "dffffffff",
1628                         driver->cversion,
1629                         driver->name,
1630                         driver->environment,
1631                         driver->driverpath,
1632                         driver->datafile,
1633                         driver->configfile,
1634                         driver->helpfile,
1635                         driver->monitorname,
1636                         driver->defaultdatatype);
1637
1638         if (driver->dependentfiles) {
1639                 for (i=0; *driver->dependentfiles[i]; i++) {
1640                         len += tdb_pack(buf+len, buflen-len, "f",
1641                                         driver->dependentfiles[i]);
1642                 }
1643         }
1644
1645         if (len != buflen) {
1646                 char *tb;
1647
1648                 tb = (char *)Realloc(buf, len);
1649                 if (!tb) {
1650                         DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1651                         ret = -1;
1652                         goto done;
1653                 }
1654                 else buf = tb;
1655                 buflen = len;
1656                 goto again;
1657         }
1658
1659
1660         kbuf.dptr = key;
1661         kbuf.dsize = strlen(key)+1;
1662         dbuf.dptr = buf;
1663         dbuf.dsize = len;
1664         
1665         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1666
1667 done:
1668         if (ret)
1669                 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1670
1671         SAFE_FREE(buf);
1672         return ret;
1673 }
1674
1675 /****************************************************************************
1676 ****************************************************************************/
1677 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1678 {
1679         NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1680
1681         ZERO_STRUCT(info3);
1682         info3.cversion = driver->version;
1683         fstrcpy(info3.name,driver->name);
1684         fstrcpy(info3.environment,driver->environment);
1685         fstrcpy(info3.driverpath,driver->driverpath);
1686         fstrcpy(info3.datafile,driver->datafile);
1687         fstrcpy(info3.configfile,driver->configfile);
1688         fstrcpy(info3.helpfile,driver->helpfile);
1689         fstrcpy(info3.monitorname,driver->monitorname);
1690         fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1691         info3.dependentfiles = driver->dependentfiles;
1692
1693         return add_a_printer_driver_3(&info3);
1694 }
1695
1696
1697 /****************************************************************************
1698 ****************************************************************************/
1699 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring driver, fstring arch)
1700 {
1701         NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1702
1703         ZERO_STRUCT(info);
1704
1705         fstrcpy(info.name, driver);
1706         fstrcpy(info.defaultdatatype, "RAW");
1707         
1708         fstrcpy(info.driverpath, "");
1709         fstrcpy(info.datafile, "");
1710         fstrcpy(info.configfile, "");
1711         fstrcpy(info.helpfile, "");
1712
1713         if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1714                 return WERR_NOMEM;
1715
1716         memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1717         fstrcpy(info.dependentfiles[0], "");
1718
1719         *info_ptr = memdup(&info, sizeof(info));
1720         
1721         return WERR_OK;
1722 }
1723
1724 /****************************************************************************
1725 ****************************************************************************/
1726 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, fstring arch, uint32 version)
1727 {
1728         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1729         TDB_DATA kbuf, dbuf;
1730         fstring architecture;
1731         int len = 0;
1732         int i;
1733         pstring key;
1734
1735         ZERO_STRUCT(driver);
1736
1737         get_short_archi(architecture, arch);
1738
1739         DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1740
1741         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1742
1743         kbuf.dptr = key;
1744         kbuf.dsize = strlen(key)+1;
1745         
1746         dbuf = tdb_fetch(tdb_drivers, kbuf);
1747         if (!dbuf.dptr) 
1748                 return WERR_ACCESS_DENIED;
1749
1750         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1751                           &driver.cversion,
1752                           driver.name,
1753                           driver.environment,
1754                           driver.driverpath,
1755                           driver.datafile,
1756                           driver.configfile,
1757                           driver.helpfile,
1758                           driver.monitorname,
1759                           driver.defaultdatatype);
1760
1761         i=0;
1762         while (len < dbuf.dsize) {
1763                 fstring *tddfs;
1764
1765                 tddfs = (fstring *)Realloc(driver.dependentfiles,
1766                                                          sizeof(fstring)*(i+2));
1767                 if (tddfs == NULL) {
1768                         DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1769                         break;
1770                 }
1771                 else driver.dependentfiles = tddfs;
1772
1773                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1774                                   &driver.dependentfiles[i]);
1775                 i++;
1776         }
1777         if (driver.dependentfiles != NULL)
1778                 fstrcpy(driver.dependentfiles[i], "");
1779
1780         SAFE_FREE(dbuf.dptr);
1781
1782         if (len != dbuf.dsize) {
1783                         SAFE_FREE(driver.dependentfiles);
1784
1785                 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1786         }
1787
1788         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1789
1790         return WERR_OK;
1791 }
1792
1793 /****************************************************************************
1794 ****************************************************************************/
1795 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1796 {
1797         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1798         TDB_DATA kbuf;
1799         pstring key;
1800         int i;
1801         line[0] = '\0';
1802
1803         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1804         DEBUG(10,("driver key: [%s]\n", key));
1805         
1806         kbuf.dptr = key;
1807         kbuf.dsize = strlen(key)+1;
1808         if (!tdb_exists(tdb_drivers, kbuf))
1809                 return False;
1810
1811         ZERO_STRUCT(info3);
1812         get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1813         
1814         DEBUGADD(10,("info3->name            [%s]\n", info3->name));
1815         DEBUGADD(10,("info3->datafile        [%s]\n", info3->datafile));
1816         DEBUGADD(10,("info3->helpfile        [%s]\n", info3->helpfile));
1817         DEBUGADD(10,("info3->monitorname     [%s]\n", info3->monitorname));
1818         DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1819         for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1820                 DEBUGADD(10,("info3->dependentfiles  [%s]\n", info3->dependentfiles[i]));
1821         }
1822         DEBUGADD(10,("info3->environment     [%s]\n", info3->environment));
1823         DEBUGADD(10,("info3->driverpath      [%s]\n", info3->driverpath));
1824         DEBUGADD(10,("info3->configfile      [%s]\n", info3->configfile));
1825
1826         /*pstrcat(line, info3->name);             pstrcat(line, ":");*/
1827         trim_string(info3->driverpath, "\\print$\\WIN40\\0\\", 0);
1828         pstrcat(line, info3->driverpath);
1829         pstrcat(line, ":");
1830         trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1831         pstrcat(line, info3->datafile);
1832         pstrcat(line, ":");
1833         trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1834         pstrcat(line, info3->helpfile);
1835         pstrcat(line, ":");
1836         trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1837         pstrcat(line, info3->monitorname);
1838         pstrcat(line, ":");
1839         pstrcat(line, "RAW");                /*info3->defaultdatatype);*/
1840         pstrcat(line, ":");
1841
1842         for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1843                 if (i)
1844                         pstrcat(line, ",");               /* don't end in a "," */
1845                 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1846                 pstrcat(line, info3->dependentfiles[i]);
1847         }
1848         
1849         SAFE_FREE(info3);
1850
1851         return True;    
1852 }
1853
1854 /****************************************************************************
1855  Debugging function, dump at level 6 the struct in the logs.
1856 ****************************************************************************/
1857
1858 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1859 {
1860         uint32 result;
1861         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1862         int i;
1863         
1864         DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1865         
1866         switch (level)
1867         {
1868                 case 3:
1869                 {
1870                         if (driver.info_3 == NULL)
1871                                 result=5;
1872                         else {
1873                                 info3=driver.info_3;
1874                         
1875                                 DEBUGADD(20,("version:[%d]\n",         info3->cversion));
1876                                 DEBUGADD(20,("name:[%s]\n",            info3->name));
1877                                 DEBUGADD(20,("environment:[%s]\n",     info3->environment));
1878                                 DEBUGADD(20,("driverpath:[%s]\n",      info3->driverpath));
1879                                 DEBUGADD(20,("datafile:[%s]\n",        info3->datafile));
1880                                 DEBUGADD(20,("configfile:[%s]\n",      info3->configfile));
1881                                 DEBUGADD(20,("helpfile:[%s]\n",        info3->helpfile));
1882                                 DEBUGADD(20,("monitorname:[%s]\n",     info3->monitorname));
1883                                 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1884                                 
1885                                 for (i=0; info3->dependentfiles &&
1886                                           *info3->dependentfiles[i]; i++) {
1887                                         DEBUGADD(20,("dependentfile:[%s]\n",
1888                                                       info3->dependentfiles[i]));
1889                                 }
1890                                 result=0;
1891                         }
1892                         break;
1893                 }
1894                 default:
1895                         DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1896                         result=1;
1897                         break;
1898         }
1899         
1900         return result;
1901 }
1902
1903 /****************************************************************************
1904 ****************************************************************************/
1905 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1906 {
1907         int len = 0;
1908
1909         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1910
1911         if (!nt_devmode) return len;
1912
1913         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1914                         nt_devmode->devicename,
1915                         nt_devmode->formname,
1916
1917                         nt_devmode->specversion,
1918                         nt_devmode->driverversion,
1919                         nt_devmode->size,
1920                         nt_devmode->driverextra,
1921                         nt_devmode->orientation,
1922                         nt_devmode->papersize,
1923                         nt_devmode->paperlength,
1924                         nt_devmode->paperwidth,
1925                         nt_devmode->scale,
1926                         nt_devmode->copies,
1927                         nt_devmode->defaultsource,
1928                         nt_devmode->printquality,
1929                         nt_devmode->color,
1930                         nt_devmode->duplex,
1931                         nt_devmode->yresolution,
1932                         nt_devmode->ttoption,
1933                         nt_devmode->collate,
1934                         nt_devmode->logpixels,
1935                         
1936                         nt_devmode->fields,
1937                         nt_devmode->bitsperpel,
1938                         nt_devmode->pelswidth,
1939                         nt_devmode->pelsheight,
1940                         nt_devmode->displayflags,
1941                         nt_devmode->displayfrequency,
1942                         nt_devmode->icmmethod,
1943                         nt_devmode->icmintent,
1944                         nt_devmode->mediatype,
1945                         nt_devmode->dithertype,
1946                         nt_devmode->reserved1,
1947                         nt_devmode->reserved2,
1948                         nt_devmode->panningwidth,
1949                         nt_devmode->panningheight,
1950                         nt_devmode->private);
1951
1952         
1953         if (nt_devmode->private) {
1954                 len += tdb_pack(buf+len, buflen-len, "B",
1955                                 nt_devmode->driverextra,
1956                                 nt_devmode->private);
1957         }
1958
1959         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1960
1961         return len;
1962 }
1963
1964 /****************************************************************************
1965 ****************************************************************************/
1966 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1967 {
1968         int len = 0;
1969
1970         while (param != NULL) {
1971                 len += tdb_pack(buf+len, buflen-len, "pfdB",
1972                                 param,
1973                                 param->value,
1974                                 param->type,
1975                                 param->data_len,
1976                                 param->data);
1977                 param=param->next;      
1978         }
1979
1980         len += tdb_pack(buf+len, buflen-len, "p", param);
1981
1982         return len;
1983 }
1984
1985
1986 /****************************************************************************
1987  Delete a printer - this just deletes the printer info file, any open
1988  handles are not affected.
1989 ****************************************************************************/
1990
1991 uint32 del_a_printer(char *sharename)
1992 {
1993         pstring key;
1994         TDB_DATA kbuf;
1995
1996         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1997
1998         kbuf.dptr=key;
1999         kbuf.dsize=strlen(key)+1;
2000
2001         tdb_delete(tdb_printers, kbuf);
2002         return 0;
2003 }
2004
2005 /* FIXME!!!  Reorder so this forward declaration is not necessary --jerry */
2006 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
2007 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
2008 /****************************************************************************
2009 ****************************************************************************/
2010 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2011 {
2012         pstring key;
2013         char *buf;
2014         int buflen, len;
2015         WERROR ret;
2016         TDB_DATA kbuf, dbuf;
2017         
2018         /*
2019          * in addprinter: no servername and the printer is the name
2020          * in setprinter: servername is \\server
2021          *                and printer is \\server\\printer
2022          *
2023          * Samba manages only local printers.
2024          * we currently don't support things like path=\\other_server\printer
2025          */
2026
2027         if (info->servername[0]!='\0') {
2028                 trim_string(info->printername, info->servername, NULL);
2029                 trim_string(info->printername, "\\", NULL);
2030                 info->servername[0]='\0';
2031         }
2032
2033         /*
2034          * JFM: one day I'll forget.
2035          * below that's info->portname because that's the SAMBA sharename
2036          * and I made NT 'thinks' it's the portname
2037          * the info->sharename is the thing you can name when you add a printer
2038          * that's the short-name when you create shared printer for 95/98
2039          * So I've made a limitation in SAMBA: you can only have 1 printer model
2040          * behind a SAMBA share.
2041          */
2042
2043         buf = NULL;
2044         buflen = 0;
2045
2046  again: 
2047         len = 0;
2048         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2049                         info->attributes,
2050                         info->priority,
2051                         info->default_priority,
2052                         info->starttime,
2053                         info->untiltime,
2054                         info->status,
2055                         info->cjobs,
2056                         info->averageppm,
2057                         info->changeid,
2058                         info->c_setprinter,
2059                         info->setuptime,
2060                         info->servername,
2061                         info->printername,
2062                         info->sharename,
2063                         info->portname,
2064                         info->drivername,
2065                         info->comment,
2066                         info->location,
2067                         info->sepfile,
2068                         info->printprocessor,
2069                         info->datatype,
2070                         info->parameters);
2071
2072         len += pack_devicemode(info->devmode, buf+len, buflen-len);
2073         
2074         len += pack_specifics(info->specific, buf+len, buflen-len);
2075
2076         if (buflen != len) {
2077                 char *tb;
2078
2079                 tb = (char *)Realloc(buf, len);
2080                 if (!tb) {
2081                         DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2082                         ret = WERR_NOMEM;
2083                         goto done;
2084                 }
2085                 else buf = tb;
2086                 buflen = len;
2087                 goto again;
2088         }
2089         
2090
2091         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2092
2093         kbuf.dptr = key;
2094         kbuf.dsize = strlen(key)+1;
2095         dbuf.dptr = buf;
2096         dbuf.dsize = len;
2097
2098         ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2099
2100 done:
2101         if (!W_ERROR_IS_OK(ret))
2102                 DEBUG(8, ("error updating printer to tdb on disk\n"));
2103
2104         SAFE_FREE(buf);
2105
2106         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2107                  info->sharename, info->drivername, info->portname, len));
2108
2109         return ret;
2110 }
2111
2112
2113 /****************************************************************************
2114 ****************************************************************************/
2115 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
2116 {
2117         NT_PRINTER_PARAM *current;
2118         
2119         DEBUG(108,("add_a_specific_param\n"));  
2120
2121         (*param)->next=NULL;
2122         
2123         if (info_2->specific == NULL)
2124         {
2125                 info_2->specific=*param;
2126         }
2127         else
2128         {
2129                 current=info_2->specific;               
2130                 while (current->next != NULL) {
2131                         current=current->next;
2132                 }               
2133                 current->next=*param;
2134         }
2135
2136         *param = NULL;
2137 }
2138
2139 /****************************************************************************
2140 ****************************************************************************/
2141 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
2142 {
2143         NT_PRINTER_PARAM *current;
2144         NT_PRINTER_PARAM *previous;
2145         
2146         current=info_2->specific;
2147         previous=current;
2148         
2149         if (current==NULL) return (False);
2150         
2151         if ( !strcmp(current->value, param->value) &&
2152             (strlen(current->value)==strlen(param->value)) ) {
2153                 DEBUG(109,("deleting first value\n"));
2154                 info_2->specific=current->next;
2155                 SAFE_FREE(current->data);
2156                 SAFE_FREE(current);
2157                 DEBUG(109,("deleted first value\n"));
2158                 return (True);
2159         }
2160
2161         current=previous->next;
2162                 
2163         while ( current!=NULL ) {
2164                 if (!strcmp(current->value, param->value) &&
2165                     strlen(current->value)==strlen(param->value) ) {
2166                         DEBUG(109,("deleting current value\n"));
2167                         previous->next=current->next;
2168                         SAFE_FREE(current->data);
2169                         SAFE_FREE(current);
2170                         DEBUG(109,("deleted current value\n"));
2171                         return(True);
2172                 }
2173                 
2174                 previous=previous->next;
2175                 current=current->next;
2176         }
2177         return (False);
2178 }
2179
2180 /****************************************************************************
2181  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2182 ****************************************************************************/
2183 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2184 {
2185         NT_PRINTER_PARAM *param = *param_ptr;
2186
2187         if(param == NULL)
2188                 return;
2189
2190         DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2191
2192                 SAFE_FREE(param->data);
2193         SAFE_FREE(*param_ptr);
2194 }
2195
2196 /****************************************************************************
2197  Malloc and return an NT devicemode.
2198 ****************************************************************************/
2199
2200 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2201 {
2202
2203         char adevice[32];
2204         NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2205
2206         if (nt_devmode == NULL) {
2207                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2208                 return NULL;
2209         }
2210
2211         ZERO_STRUCTP(nt_devmode);
2212
2213         safe_strcpy(adevice, default_devicename, sizeof(adevice));
2214         fstrcpy(nt_devmode->devicename, adevice);       
2215         
2216         fstrcpy(nt_devmode->formname, "Letter");
2217
2218         nt_devmode->specversion      = 0x0401;
2219         nt_devmode->driverversion    = 0x0400;
2220         nt_devmode->size             = 0x00DC;
2221         nt_devmode->driverextra      = 0x0000;
2222         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY |
2223                                        DEFAULTSOURCE | COPIES | SCALE |
2224                                        PAPERSIZE | ORIENTATION;
2225         nt_devmode->orientation      = 1;
2226         nt_devmode->papersize        = PAPER_LETTER;
2227         nt_devmode->paperlength      = 0;
2228         nt_devmode->paperwidth       = 0;
2229         nt_devmode->scale            = 0x64;
2230         nt_devmode->copies           = 1;
2231         nt_devmode->defaultsource    = BIN_FORMSOURCE;
2232         nt_devmode->printquality     = RES_HIGH;           /* 0x0258 */
2233         nt_devmode->color            = COLOR_MONOCHROME;
2234         nt_devmode->duplex           = DUP_SIMPLEX;
2235         nt_devmode->yresolution      = 0;
2236         nt_devmode->ttoption         = TT_SUBDEV;
2237         nt_devmode->collate          = COLLATE_FALSE;
2238         nt_devmode->icmmethod        = 0;
2239         nt_devmode->icmintent        = 0;
2240         nt_devmode->mediatype        = 0;
2241         nt_devmode->dithertype       = 0;
2242
2243         /* non utilisés par un driver d'imprimante */
2244         nt_devmode->logpixels        = 0;
2245         nt_devmode->bitsperpel       = 0;
2246         nt_devmode->pelswidth        = 0;
2247         nt_devmode->pelsheight       = 0;
2248         nt_devmode->displayflags     = 0;
2249         nt_devmode->displayfrequency = 0;
2250         nt_devmode->reserved1        = 0;
2251         nt_devmode->reserved2        = 0;
2252         nt_devmode->panningwidth     = 0;
2253         nt_devmode->panningheight    = 0;
2254         
2255         nt_devmode->private = NULL;
2256         return nt_devmode;
2257 }
2258
2259 /****************************************************************************
2260  Deepcopy an NT devicemode.
2261 ****************************************************************************/
2262
2263 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2264 {
2265         NT_DEVICEMODE *new_nt_devicemode = NULL;
2266
2267         if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2268                 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2269                 return NULL;
2270         }
2271
2272         new_nt_devicemode->private = NULL;
2273         if (nt_devicemode->private != NULL) {
2274                 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2275                         SAFE_FREE(new_nt_devicemode);
2276                         DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2277                         return NULL;
2278         }
2279         }
2280
2281         return new_nt_devicemode;
2282 }
2283
2284 /****************************************************************************
2285  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2286 ****************************************************************************/
2287
2288 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2289 {
2290         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2291
2292         if(nt_devmode == NULL)
2293                 return;
2294
2295         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2296
2297                 SAFE_FREE(nt_devmode->private);
2298         SAFE_FREE(*devmode_ptr);
2299 }
2300
2301 /****************************************************************************
2302  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2303 ****************************************************************************/
2304 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2305 {
2306         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2307         NT_PRINTER_PARAM *param_ptr;
2308
2309         if(info == NULL)
2310                 return;
2311
2312         DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2313
2314         free_nt_devicemode(&info->devmode);
2315
2316         for(param_ptr = info->specific; param_ptr; ) {
2317                 NT_PRINTER_PARAM *tofree = param_ptr;
2318
2319                 param_ptr = param_ptr->next;
2320                 free_nt_printer_param(&tofree);
2321         }
2322
2323         SAFE_FREE(*info_ptr);
2324 }
2325
2326
2327 /****************************************************************************
2328 ****************************************************************************/
2329 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2330 {
2331         int len = 0;
2332         int extra_len = 0;
2333         NT_DEVICEMODE devmode;
2334
2335         ZERO_STRUCT(devmode);
2336
2337         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2338
2339         if (!*nt_devmode) return len;
2340
2341         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2342                           devmode.devicename,
2343                           devmode.formname,
2344
2345                           &devmode.specversion,
2346                           &devmode.driverversion,
2347                           &devmode.size,
2348                           &devmode.driverextra,
2349                           &devmode.orientation,
2350                           &devmode.papersize,
2351                           &devmode.paperlength,
2352                           &devmode.paperwidth,
2353                           &devmode.scale,
2354                           &devmode.copies,
2355                           &devmode.defaultsource,
2356                           &devmode.printquality,
2357                           &devmode.color,
2358                           &devmode.duplex,
2359                           &devmode.yresolution,
2360                           &devmode.ttoption,
2361                           &devmode.collate,
2362                           &devmode.logpixels,
2363                         
2364                           &devmode.fields,
2365                           &devmode.bitsperpel,
2366                           &devmode.pelswidth,
2367                           &devmode.pelsheight,
2368                           &devmode.displayflags,
2369                           &devmode.displayfrequency,
2370                           &devmode.icmmethod,
2371                           &devmode.icmintent,
2372                           &devmode.mediatype,
2373                           &devmode.dithertype,
2374                           &devmode.reserved1,
2375                           &devmode.reserved2,
2376                           &devmode.panningwidth,
2377                           &devmode.panningheight,
2378                           &devmode.private);
2379         
2380         if (devmode.private) {
2381                 /* the len in tdb_unpack is an int value and
2382                  * devmode.driverextra is only a short
2383                  */
2384                 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2385                 devmode.driverextra=(uint16)extra_len;
2386                 
2387                 /* check to catch an invalid TDB entry so we don't segfault */
2388                 if (devmode.driverextra == 0) {
2389                         devmode.private = NULL;
2390                 }
2391         }
2392
2393         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2394
2395         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2396         if (devmode.private)
2397                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2398
2399         return len;
2400 }
2401
2402 /****************************************************************************
2403 ****************************************************************************/
2404 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2405 {
2406         int len = 0;
2407         NT_PRINTER_PARAM param, *p;
2408
2409         *list = NULL;
2410
2411         while (1) {
2412                 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2413                 if (!p) break;
2414
2415                 len += tdb_unpack(buf+len, buflen-len, "fdB",
2416                                   param.value,
2417                                   &param.type,
2418                                   &param.data_len,
2419                                   &param.data);
2420                 param.next = *list;
2421                 *list = memdup(&param, sizeof(param));
2422
2423                 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2424         }
2425
2426         return len;
2427 }
2428
2429 static void map_to_os2_driver(fstring drivername)
2430 {
2431         static BOOL initialised=False;
2432         static fstring last_from,last_to;
2433         char *mapfile = lp_os2_driver_map();
2434         char **lines = NULL;
2435         int numlines = 0;
2436         int i;
2437
2438         if (!strlen(drivername))
2439                 return;
2440
2441         if (!*mapfile)
2442                 return;
2443
2444         if (!initialised) {
2445                 *last_from = *last_to = 0;
2446                 initialised = True;
2447         }
2448
2449         if (strequal(drivername,last_from)) {
2450                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2451                 fstrcpy(drivername,last_to);
2452                 return;
2453         }
2454
2455         lines = file_lines_load(mapfile, &numlines);
2456         if (numlines == 0) {
2457                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2458                 return;
2459         }
2460
2461         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2462
2463         for( i = 0; i < numlines; i++) {
2464                 char *nt_name = lines[i];
2465                 char *os2_name = strchr(nt_name,'=');
2466
2467                 if (!os2_name)
2468                         continue;
2469
2470                 *os2_name++ = 0;
2471
2472                 while (isspace(*nt_name))
2473                         nt_name++;
2474
2475                 if (!*nt_name || strchr("#;",*nt_name))
2476                         continue;
2477
2478                 {
2479                         int l = strlen(nt_name);
2480                         while (l && isspace(nt_name[l-1])) {
2481                                 nt_name[l-1] = 0;
2482                                 l--;
2483                         }
2484                 }
2485
2486                 while (isspace(*os2_name))
2487                         os2_name++;
2488
2489                 {
2490                         int l = strlen(os2_name);
2491                         while (l && isspace(os2_name[l-1])) {
2492                                 os2_name[l-1] = 0;
2493                                 l--;
2494                         }
2495                 }
2496
2497                 if (strequal(nt_name,drivername)) {
2498                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2499                         fstrcpy(last_from,drivername);
2500                         fstrcpy(last_to,os2_name);
2501                         fstrcpy(drivername,os2_name);
2502                         file_lines_free(lines);
2503                         return;
2504                 }
2505         }
2506
2507         file_lines_free(lines);
2508 }
2509
2510 /****************************************************************************
2511 get a default printer info 2 struct
2512 ****************************************************************************/
2513 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2514 {
2515         int snum;
2516         NT_PRINTER_INFO_LEVEL_2 info;
2517
2518         ZERO_STRUCT(info);
2519
2520         snum = lp_servicenumber(sharename);
2521
2522         slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2523         slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s", 
2524                  get_called_name(), sharename);
2525         fstrcpy(info.sharename, sharename);
2526         fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2527         fstrcpy(info.drivername, lp_printerdriver(snum));
2528
2529         /* by setting the driver name to an empty string, a local NT admin
2530            can now run the **local** APW to install a local printer driver
2531            for a Samba shared printer in 2.2.  Without this, drivers **must** be 
2532            installed on the Samba server for NT clients --jerry */
2533 #if 0   /* JERRY --do not uncomment-- */
2534         if (!*info.drivername)
2535                 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2536 #endif
2537
2538
2539         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2540
2541         pstrcpy(info.comment, "");
2542         fstrcpy(info.printprocessor, "winprint");
2543         fstrcpy(info.datatype, "RAW");
2544
2545         info.attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK;      /* attributes */
2546
2547         info.starttime = 0; /* Minutes since 12:00am GMT */
2548         info.untiltime = 0; /* Minutes since 12:00am GMT */
2549         info.priority = 1;
2550         info.default_priority = 1;
2551         info.setuptime = (uint32)time(NULL);
2552
2553         /*
2554          * I changed this as I think it is better to have a generic
2555          * DEVMODE than to crash Win2k explorer.exe   --jerry
2556          * See the HP Deskjet 990c Win2k drivers for an example.
2557          *
2558          * However the default devmode appears to cause problems
2559          * with the HP CLJ 8500 PCL driver.  Hence the addition of
2560          * the "default devmode" parameter   --jerry 22/01/2002
2561          */
2562
2563         if (lp_default_devmode(snum)) {
2564                 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2565                         goto fail;
2566         }
2567         else {
2568                 info.devmode = NULL;
2569         }
2570
2571         /* This will get the current RPC talloc context, but we should be
2572            passing this as a parameter... fixme... JRA ! */
2573
2574         if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2575                 goto fail;
2576
2577         *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2578         if (! *info_ptr) {
2579                 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2580                 goto fail;
2581         }
2582
2583         return WERR_OK;
2584
2585   fail:
2586         if (info.devmode)
2587                 free_nt_devicemode(&info.devmode);
2588         return WERR_ACCESS_DENIED;
2589 }
2590
2591 /****************************************************************************
2592 ****************************************************************************/
2593 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2594 {
2595         pstring key;
2596         NT_PRINTER_INFO_LEVEL_2 info;
2597         int             len = 0;
2598         TDB_DATA kbuf, dbuf;
2599         fstring printername;
2600                 
2601         ZERO_STRUCT(info);
2602
2603         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2604
2605         kbuf.dptr = key;
2606         kbuf.dsize = strlen(key)+1;
2607
2608         dbuf = tdb_fetch(tdb_printers, kbuf);
2609         if (!dbuf.dptr)
2610                 return get_a_printer_2_default(info_ptr, sharename);
2611
2612         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2613                         &info.attributes,
2614                         &info.priority,
2615                         &info.default_priority,
2616                         &info.starttime,
2617                         &info.untiltime,
2618                         &info.status,
2619                         &info.cjobs,
2620                         &info.averageppm,
2621                         &info.changeid,
2622                         &info.c_setprinter,
2623                         &info.setuptime,
2624                         info.servername,
2625                         info.printername,
2626                         info.sharename,
2627                         info.portname,
2628                         info.drivername,
2629                         info.comment,
2630                         info.location,
2631                         info.sepfile,
2632                         info.printprocessor,
2633                         info.datatype,
2634                         info.parameters);
2635
2636         /* Samba has to have shared raw drivers. */
2637         info.attributes |= (PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK); 
2638
2639         /* Restore the stripped strings. */
2640         slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2641         slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
2642                         info.printername);
2643         fstrcpy(info.printername, printername);
2644
2645         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2646
2647         /*
2648          * Some client drivers freak out if there is a NULL devmode
2649          * (probably the driver is not checking before accessing 
2650          * the devmode pointer)   --jerry
2651          *
2652          * See comments in get_a_printer_2_default()
2653          */
2654
2655         if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode)
2656         {
2657                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
2658                         printername));
2659                 info.devmode = construct_nt_devicemode(printername);
2660         }
2661
2662         len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2663
2664         /* This will get the current RPC talloc context, but we should be
2665        passing this as a parameter... fixme... JRA ! */
2666
2667         nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2668
2669         /* Fix for OS/2 drivers. */
2670
2671         if (get_remote_arch() == RA_OS2)
2672                 map_to_os2_driver(info.drivername);
2673
2674         SAFE_FREE(dbuf.dptr);
2675         *info_ptr=memdup(&info, sizeof(info));
2676
2677         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2678                  sharename, info.printername, info.drivername));
2679
2680         return WERR_OK; 
2681 }
2682
2683 /****************************************************************************
2684 debugging function, dump at level 6 the struct in the logs
2685 ****************************************************************************/
2686 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2687 {
2688         uint32 result;
2689         NT_PRINTER_INFO_LEVEL_2 *info2;
2690         
2691         DEBUG(106,("Dumping printer at level [%d]\n", level));
2692         
2693         switch (level)
2694         {
2695                 case 2:
2696                 {
2697                         if (printer.info_2 == NULL)
2698                                 result=5;
2699                         else
2700                         {
2701                                 info2=printer.info_2;
2702                         
2703                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2704                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2705                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2706                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2707                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2708                                 DEBUGADD(106,("status:[%d]\n", info2->status));
2709                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2710                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2711                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2712                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2713                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2714
2715                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2716                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2717                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2718                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2719                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2720                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2721                                 DEBUGADD(106,("location:[%s]\n", info2->location));
2722                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2723                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2724                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2725                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2726                                 result=0;
2727                         }
2728                         break;
2729                 }
2730                 default:
2731                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
2732                         result=1;
2733                         break;
2734         }
2735         
2736         return result;
2737 }
2738
2739 /****************************************************************************
2740  Get the parameters we can substitute in an NT print job.
2741 ****************************************************************************/
2742
2743 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2744 {
2745         NT_PRINTER_INFO_LEVEL *printer = NULL;
2746
2747         **printername = **sharename = **portname = '\0';
2748
2749         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2750                 return;
2751
2752         fstrcpy(*printername, printer->info_2->printername);
2753         fstrcpy(*sharename, printer->info_2->sharename);
2754         fstrcpy(*portname, printer->info_2->portname);
2755
2756         free_a_printer(&printer, 2);
2757 }
2758
2759 /****************************************************************************
2760  Update the changeid time.
2761  This is SO NASTY as some drivers need this to change, others need it
2762  static. This value will change every second, and I must hope that this
2763  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
2764  UTAH ! JRA.
2765 ****************************************************************************/
2766
2767 static uint32 rev_changeid(void)
2768 {
2769         struct timeval tv;
2770
2771         get_process_uptime(&tv);
2772
2773 #if 1   /* JERRY */
2774         /* Return changeid as msec since spooler restart */
2775         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
2776 #else
2777         /*
2778          * This setting seems to work well but is too untested
2779          * to replace the above calculation.  Left in for experiementation
2780          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
2781          */
2782         return tv.tv_sec * 10 + tv.tv_usec / 100000;
2783 #endif
2784 }
2785
2786 /*
2787  * The function below are the high level ones.
2788  * only those ones must be called from the spoolss code.
2789  * JFM.
2790  */
2791
2792 /****************************************************************************
2793  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2794 ****************************************************************************/
2795
2796 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2797 {
2798         WERROR result;
2799         
2800         dump_a_printer(printer, level); 
2801         
2802         switch (level)
2803         {
2804                 case 2:
2805                 {
2806                         /*
2807                          * Update the changestamp.  Emperical tests show that the
2808                          * ChangeID is always updated,but c_setprinter is  
2809                          *  global spooler variable (not per printer).
2810                          */
2811
2812                         /* ChangeID **must** be increasing over the lifetime
2813                            of client's spoolss service in order for the
2814                            client's cache to show updates */
2815
2816                         printer.info_2->changeid = rev_changeid();
2817
2818                         /*
2819                          * Because one day someone will ask:
2820                          * NT->NT       An admin connection to a remote
2821                          *              printer show changes imeediately in
2822                          *              the properities dialog
2823                          *      
2824                          *              A non-admin connection will only show the
2825                          *              changes after viewing the properites page
2826                          *              2 times.  Seems to be related to a
2827                          *              race condition in the client between the spooler
2828                          *              updating the local cache and the Explorer.exe GUI
2829                          *              actually displaying the properties.
2830                          *
2831                          *              This is fixed in Win2k.  admin/non-admin
2832                          *              connections both display changes immediately.
2833                          *
2834                          * 14/12/01     --jerry
2835                          */
2836
2837                         result=update_a_printer_2(printer.info_2);
2838                         break;
2839                 }
2840                 default:
2841                         result=WERR_UNKNOWN_LEVEL;
2842                         break;
2843         }
2844         
2845         return result;
2846 }
2847
2848 /****************************************************************************
2849  Initialize printer devmode & data with previously saved driver init values.
2850 ****************************************************************************/
2851
2852 static BOOL set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
2853 {
2854         int                     len = 0;
2855         pstring                 key;
2856         TDB_DATA                kbuf, dbuf;
2857         NT_PRINTER_PARAM        *current;
2858         NT_PRINTER_INFO_LEVEL_2 info;
2859
2860         /*
2861          * Delete any printer data 'specifics' already set. When called for driver
2862          * replace, there will generally be some, but during an add printer, there
2863          * should not be any (if there are delete them).
2864          */
2865         while ( (current=info_ptr->specific) != NULL ) {
2866                 info_ptr->specific=current->next;
2867                 SAFE_FREE(current->data);
2868                 SAFE_FREE(current);
2869         }
2870
2871         ZERO_STRUCT(info);
2872
2873         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
2874
2875         kbuf.dptr = key;
2876         kbuf.dsize = strlen(key)+1;
2877
2878         dbuf = tdb_fetch(tdb_drivers, kbuf);
2879     if (!dbuf.dptr) {
2880                 /*
2881                  * When changing to a driver that has no init info in the tdb, remove
2882                  * the previous drivers init info and leave the new on blank.
2883                  */
2884                 free_nt_devicemode(&info_ptr->devmode);
2885                 return False;
2886         }
2887
2888         /*
2889          * Get the saved DEVMODE..
2890          */
2891         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2892
2893         /*
2894          * The saved DEVMODE contains the devicename from the printer used during
2895          * the initialization save. Change it to reflect the new printer.
2896          */
2897         ZERO_STRUCT(info.devmode->devicename);
2898         fstrcpy(info.devmode->devicename, info_ptr->printername);
2899
2900
2901         /*
2902          * NT/2k does not change out the entire DeviceMode of a printer
2903          * when changing the driver.  Only the driverextra, private, & 
2904          * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
2905          *
2906          * Later e4xamination revealed that Windows NT/2k does reset the
2907          * the printer's device mode, bit **only** when you change a 
2908          * property of the device mode such as the page orientation.
2909          * --jerry
2910          */
2911
2912 #if 1   /* JERRY */
2913
2914         /* 
2915          *      Bind the saved DEVMODE to the new the printer.
2916          */
2917         free_nt_devicemode(&info_ptr->devmode);
2918         info_ptr->devmode = info.devmode;
2919 #else
2920         /* copy the entire devmode if we currently don't have one */
2921
2922         if (!info_ptr->devmode) {
2923                 DEBUG(10,("set_driver_init_2: Current Devmode is NULL.  Copying entire Device Mode\n"));
2924                 info_ptr->devmode = info.devmode;
2925         }
2926         else {
2927                 /* only set the necessary fields */
2928
2929                 DEBUG(10,("set_driver_init_2: Setting driverversion [0x%x] and private data [0x%x]\n",
2930                         info.devmode->driverversion, info.devmode->driverextra));
2931
2932                 info_ptr->devmode->driverversion = info.devmode->driverversion;
2933
2934                 SAFE_FREE(info_ptr->devmode->private);
2935                 info_ptr->devmode->private = NULL;
2936
2937                 if (info.devmode->driverversion)
2938                         info_ptr->devmode->private = memdup(info.devmode->private, info.devmode->driverversion);
2939
2940                 free_nt_devicemode(&info.devmode);
2941         }
2942 #endif
2943
2944         DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
2945                         info_ptr->printername, info_ptr->drivername));
2946
2947         /* 
2948          * Add the printer data 'specifics' to the new printer
2949          */
2950         len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len);
2951
2952         SAFE_FREE(dbuf.dptr);
2953
2954         return True;    
2955 }
2956
2957 /****************************************************************************
2958  Initialize printer devmode & data with previously saved driver init values.
2959  When a printer is created using AddPrinter, the drivername bound to the
2960  printer is used to lookup previously saved driver initialization info, which
2961  is bound to the new printer.
2962 ****************************************************************************/
2963
2964 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
2965 {
2966         BOOL result = False;
2967         
2968         switch (level)
2969         {
2970                 case 2:
2971                         result=set_driver_init_2(printer->info_2);
2972                         break;
2973                         
2974                 default:
2975                         DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
2976                                 level));
2977                         break;
2978         }
2979         
2980         return result;
2981 }
2982
2983 /****************************************************************************
2984  Delete driver init data stored for a specified driver
2985 ****************************************************************************/
2986
2987 BOOL del_driver_init(char *drivername)
2988 {
2989         pstring key;
2990         TDB_DATA kbuf;
2991
2992         if (!drivername || !*drivername) {
2993                 DEBUG(3,("del_driver_init: No drivername specified!\n"));
2994                 return False;
2995         }
2996
2997         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
2998
2999         kbuf.dptr = key;
3000         kbuf.dsize = strlen(key)+1;
3001
3002         DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3003
3004         return (tdb_delete(tdb_drivers, kbuf) == 0);
3005 }
3006
3007 /****************************************************************************
3008  Pack up the DEVMODE and specifics for a printer into a 'driver init' entry 
3009  in the tdb. Note: this is different from the driver entry and the printer
3010  entry. There should be a single driver init entry for each driver regardless
3011  of whether it was installed from NT or 2K. Technically, they should be
3012  different, but they work out to the same struct.
3013 ****************************************************************************/
3014
3015 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3016 {
3017         pstring key;
3018         char *buf;
3019         int buflen, len, ret;
3020         TDB_DATA kbuf, dbuf;
3021
3022         buf = NULL;
3023         buflen = 0;
3024
3025  again: 
3026         len = 0;
3027         len += pack_devicemode(info->devmode, buf+len, buflen-len);
3028
3029         len += pack_specifics(info->specific, buf+len, buflen-len);
3030
3031         if (buflen != len) {
3032                 char *tb;
3033
3034                 tb = (char *)Realloc(buf, len);
3035                 if (!tb) {
3036                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3037                         ret = -1;
3038                         goto done;
3039                 }
3040                 else buf = tb;
3041                 buflen = len;
3042                 goto again;
3043         }
3044
3045         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3046
3047         kbuf.dptr = key;
3048         kbuf.dsize = strlen(key)+1;
3049         dbuf.dptr = buf;
3050         dbuf.dsize = len;
3051
3052         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3053
3054 done:
3055         if (ret == -1)
3056                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3057
3058         SAFE_FREE(buf);
3059
3060         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n",
3061                  info->sharename, info->drivername));
3062
3063         return ret;
3064 }
3065
3066 /****************************************************************************
3067  Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer
3068 ****************************************************************************/
3069
3070 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3071 {
3072         uint32 result;
3073         
3074         dump_a_printer(printer, level); 
3075         
3076         switch (level)
3077         {
3078                 case 2:
3079                 {
3080                         result=update_driver_init_2(printer.info_2);
3081                         break;
3082                 }
3083                 default:
3084                         result=1;
3085                         break;
3086         }
3087         
3088         return result;
3089 }
3090
3091 /****************************************************************************
3092  Convert the printer data value, a REG_BINARY array, into an initialization 
3093  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3094  got to keep the endians happy :).
3095 ****************************************************************************/
3096
3097 static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode)
3098 {
3099         BOOL       result = False;
3100         prs_struct ps;
3101         DEVICEMODE devmode;
3102
3103         ZERO_STRUCT(devmode);
3104
3105         prs_init(&ps, 0, ctx, UNMARSHALL);
3106         ps.data_p      = (char *)param->data;
3107         ps.buffer_size = param->data_len;
3108
3109         if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3110                 result = convert_devicemode("", &devmode, &nt_devmode);
3111         else
3112                 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3113
3114         return result;
3115 }
3116
3117 /****************************************************************************
3118  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3119
3120  1. Use the driver's config DLL to this UNC printername and:
3121     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3122     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3123  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3124
3125  The last step triggers saving the "driver initialization" information for
3126  this printer into the tdb. Later, new printers that use this driver will
3127  have this initialization information bound to them. This simulates the
3128  driver initialization, as if it had run on the Samba server (as it would
3129  have done on NT).
3130
3131  The Win32 client side code requirement sucks! But until we can run arbitrary
3132  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3133  
3134  It would have been easier to use SetPrinter because all the UNMARSHALLING of
3135  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3136  about it and you will realize why.  JRR 010720
3137 ****************************************************************************/
3138
3139 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
3140 {
3141         WERROR        status       = WERR_OK;
3142         TALLOC_CTX    *ctx         = NULL;
3143         NT_DEVICEMODE *nt_devmode  = NULL;
3144         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3145         
3146         /*
3147          * When the DEVMODE is already set on the printer, don't try to unpack it.
3148          */
3149
3150         if (!printer->info_2->devmode && param->data_len) {
3151                 /*
3152                  * Set devmode on printer info, so entire printer initialization can be
3153                  * saved to tdb.
3154                  */
3155
3156                 if ((ctx = talloc_init()) == NULL)
3157                         return WERR_NOMEM;
3158
3159                 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3160                         status = WERR_NOMEM;
3161                         goto done;
3162                 }
3163         
3164                 ZERO_STRUCTP(nt_devmode);
3165
3166                 /*
3167                  * The DEVMODE is held in the 'data' component of the param in raw binary.
3168                  * Convert it to to a devmode structure
3169                  */
3170                 if (!convert_driver_init(param, ctx, nt_devmode)) {
3171                         DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3172                         status = WERR_INVALID_PARAM;
3173                         goto done;
3174                 }
3175
3176                 printer->info_2->devmode = nt_devmode;
3177         }
3178
3179         /*
3180          * Pack up and add (or update) the DEVMODE and any current printer data to
3181          * a 'driver init' element in the tdb
3182          * 
3183          */
3184
3185         if (update_driver_init(*printer, 2)!=0) {
3186                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3187                 status = WERR_NOMEM;
3188                 goto done;
3189         }
3190         
3191         /*
3192          * If driver initialization info was successfully saved, set the current 
3193          * printer to match it. This allows initialization of the current printer 
3194          * as well as the driver.
3195          */
3196         status = mod_a_printer(*printer, 2);
3197         if (!W_ERROR_IS_OK(status)) {
3198                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3199                                   printer->info_2->printername));
3200         }
3201         
3202 #if 0   /* JERRY */
3203         srv_spoolss_sendnotify(p, handle);
3204 #endif
3205
3206   done:
3207         talloc_destroy(ctx);
3208         if (nt_devmode)
3209                 SAFE_FREE(nt_devmode->private);
3210         SAFE_FREE(nt_devmode);
3211         printer->info_2->devmode = tmp_devmode;
3212
3213         return status;
3214 }
3215
3216 /****************************************************************************
3217  Update the driver init info (DEVMODE and specifics) for a printer
3218 ****************************************************************************/
3219
3220 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
3221 {
3222         WERROR status = WERR_OK;
3223         
3224         switch (level)
3225         {
3226                 case 2:
3227                 {
3228                         status=save_driver_init_2(printer, param);
3229                         break;
3230                 }
3231                 default:
3232                         status=WERR_UNKNOWN_LEVEL;
3233                         break;
3234         }
3235         
3236         return status;
3237 }
3238
3239 /****************************************************************************
3240  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3241 ****************************************************************************/
3242
3243 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
3244 {
3245         WERROR result;
3246         NT_PRINTER_INFO_LEVEL *printer = NULL;
3247         
3248         *pp_printer = NULL;
3249
3250         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3251
3252         switch (level)
3253         {
3254                 case 2:
3255                 {
3256                         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3257                                 DEBUG(0,("get_a_printer: malloc fail.\n"));
3258                                 return WERR_NOMEM;
3259                         }
3260                         ZERO_STRUCTP(printer);
3261                         result=get_a_printer_2(&printer->info_2, sharename);
3262                         if (W_ERROR_IS_OK(result)) {
3263                                 dump_a_printer(*printer, level);
3264                                 *pp_printer = printer;
3265                         } else {
3266                                 SAFE_FREE(printer);
3267                         }
3268                         break;
3269                 }
3270                 default:
3271                         result=WERR_UNKNOWN_LEVEL;
3272                         break;
3273         }
3274         
3275         DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
3276
3277         return result;
3278 }
3279
3280 /****************************************************************************
3281  Deletes a NT_PRINTER_INFO_LEVEL struct.
3282 ****************************************************************************/
3283
3284 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3285 {
3286         uint32 result;
3287         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3288
3289         DEBUG(104,("freeing a printer at level [%d]\n", level));
3290
3291         if (printer == NULL)
3292                 return 0;
3293         
3294         switch (level)
3295         {
3296                 case 2:
3297                 {
3298                         if (printer->info_2 != NULL)
3299                         {
3300                                 free_nt_printer_info_level_2(&printer->info_2);
3301                                 result=0;
3302                         }
3303                         else
3304                         {
3305                                 result=4;
3306                         }
3307                         break;
3308                 }
3309                 default:
3310                         result=1;
3311                         break;
3312         }
3313
3314         SAFE_FREE(*pp_printer);
3315         return result;
3316 }
3317
3318 /****************************************************************************
3319 ****************************************************************************/
3320 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3321 {
3322         uint32 result;
3323         DEBUG(104,("adding a printer at level [%d]\n", level));
3324         dump_a_printer_driver(driver, level);
3325         
3326         switch (level)
3327         {
3328                 case 3:
3329                 {
3330                         result=add_a_printer_driver_3(driver.info_3);
3331                         break;
3332                 }
3333
3334                 case 6:
3335                 {
3336                         result=add_a_printer_driver_6(driver.info_6);
3337                         break;
3338                 }
3339                 default:
3340                         result=1;
3341                         break;
3342         }
3343         
3344         return result;
3345 }
3346 /****************************************************************************
3347 ****************************************************************************/
3348 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3349                             fstring drivername, fstring architecture, uint32 version)
3350 {
3351         WERROR result;
3352         
3353         switch (level)
3354         {
3355                 case 3:
3356                         /* Sometime we just want any version of the driver */
3357                         
3358                         if ( version == DRIVER_ANY_VERSION ) {
3359                                 /* look for Win2k first and then for NT4 */
3360                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
3361                                                 architecture, 3);
3362                                                 
3363                                 if ( !W_ERROR_IS_OK(result) ) {
3364                                         result = get_a_printer_driver_3( &driver->info_3, 
3365                                                         drivername, architecture, 2 );
3366                                 }
3367                         }
3368                         else {
3369                                 result = get_a_printer_driver_3(&driver->info_3, drivername, 
3370                                         architecture, version);                         
3371                         }
3372                         break;
3373                         
3374                 default:
3375                         result=W_ERROR(1);
3376                         break;
3377         }
3378         
3379         if (W_ERROR_IS_OK(result))
3380                 dump_a_printer_driver(*driver, level);
3381                 
3382         return result;
3383 }
3384
3385 /****************************************************************************
3386 ****************************************************************************/
3387 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3388 {
3389         uint32 result;
3390         
3391         switch (level)
3392         {
3393                 case 3:
3394                 {
3395                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3396                         if (driver.info_3 != NULL)
3397                         {
3398                                 info3=driver.info_3;
3399                                 SAFE_FREE(info3->dependentfiles);
3400                                 ZERO_STRUCTP(info3);
3401                                 SAFE_FREE(info3);
3402                                 result=0;
3403                         }
3404                         else
3405                         {
3406                                 result=4;
3407                         }
3408                         break;
3409                 }
3410                 case 6:
3411                 {
3412                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3413                         if (driver.info_6 != NULL)
3414                         {
3415                                 info6=driver.info_6;
3416                                 SAFE_FREE(info6->dependentfiles);
3417                                 SAFE_FREE(info6->previousnames);
3418                                 ZERO_STRUCTP(info6);
3419                                 SAFE_FREE(info6);
3420                                 result=0;
3421                         }
3422                         else
3423                         {
3424                                 result=4;
3425                         }
3426                         break;
3427                 }
3428                 default:
3429                         result=1;
3430                         break;
3431         }
3432         return result;
3433 }
3434
3435
3436 /****************************************************************************
3437   Determine whether or not a particular driver is currently assigned
3438   to a printer
3439 ****************************************************************************/
3440
3441 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i )
3442 {
3443         int snum;
3444         int n_services = lp_numservices();
3445         NT_PRINTER_INFO_LEVEL *printer = NULL;
3446
3447         if ( !i ) 
3448                 return False;
3449
3450         DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
3451         
3452         /* loop through the printers.tdb and check for the drivername */
3453         
3454         for (snum=0; snum<n_services; snum++) 
3455         {
3456                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
3457                         continue;
3458                 
3459                 if ( !W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) )
3460                         continue;
3461                 
3462                 if ( !StrCaseCmp(i->name, printer->info_2->drivername) ) {
3463                         free_a_printer( &printer, 2 );
3464                         return True;
3465                 }
3466                 
3467                 free_a_printer( &printer, 2 );
3468         }
3469         
3470         DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
3471         
3472         /* report that the driver is not in use by default */
3473         
3474         return False;
3475 }
3476
3477
3478 /**********************************************************************
3479  Check to see if a ogiven file is in use by *info
3480  *********************************************************************/
3481  
3482 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
3483 {
3484         char *s;
3485         
3486         if ( !info )
3487                 return False;
3488                 
3489         if ( strequal(file, info->driverpath) )
3490                 return True;
3491
3492         if ( strequal(file, info->datafile) )
3493                 return True;
3494
3495         if ( strequal(file, info->configfile) )
3496                 return True;
3497
3498         if ( strequal(file, info->helpfile) )
3499                 return True;
3500                 
3501         s = (char*) info->dependentfiles;
3502         
3503         if ( s ) {
3504                 while ( *s )
3505                 {
3506                         if ( strequal(file, s) )
3507                                 return True;
3508                         s += strlen(s) + 1;
3509                 }
3510         }
3511         
3512         return False;
3513
3514 }
3515
3516 /**********************************************************************
3517  Utility function to remove the dependent file pointed to by the 
3518  input parameter from the list 
3519  *********************************************************************/
3520
3521 static void trim_dependent_file( char* s )
3522 {
3523         char *p;
3524         
3525         /* set p to the next character string in the list */
3526         
3527         p = s + strlen( s ) + 1;
3528         
3529         /* check to see that we have another string to copy back */
3530         
3531         if ( *p == '\0' ) 
3532         {
3533                 /* loop over s copying characters from p to s */
3534                 while ( *p!='\0' && *(p+1)!='\0' )
3535                         *s++ = *p++;
3536         }
3537         
3538         /* add the two trailing NULL's */
3539         
3540         *s      = '\0';
3541         *(s+1)  = '\0';
3542 }
3543
3544 /**********************************************************************
3545  Check if any of the files used by src are also used by drv 
3546  *********************************************************************/
3547
3548 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, 
3549                                        NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
3550 {
3551         BOOL in_use = False;
3552         char *s;
3553         
3554         if ( !src || !drv )
3555                 return False;
3556                 
3557         /* check each file.  Remove it from the src structure if it overlaps */
3558         
3559         if ( drv_file_in_use(src->driverpath, drv) ) {
3560                 in_use = True;
3561                 fstrcpy( src->driverpath, "" );
3562         }
3563                 
3564         if ( drv_file_in_use(src->datafile, drv) ) {
3565                 in_use = True;
3566                 fstrcpy( src->datafile, "" );
3567         }
3568                 
3569         if ( drv_file_in_use(src->configfile, drv) ) {
3570                 in_use = True;
3571                 fstrcpy( src->configfile, "" );
3572         }
3573                 
3574         s = (char*)src->dependentfiles;
3575         
3576         if ( s ) {
3577                 while ( *s ) 
3578                 {
3579                         if ( drv_file_in_use(s, drv) ) {
3580                                 in_use = True;
3581                                 trim_dependent_file( s );
3582                         }
3583                         else
3584                                 s += strlen(s) + 1;     
3585                 } 
3586         }
3587                 
3588                 
3589         return in_use;
3590 }
3591
3592 /****************************************************************************
3593   Determine whether or not a particular driver files are currently being 
3594   used by any other driver.  
3595   
3596   Return value is True if any files were in use by other drivers
3597   and False otherwise.
3598   
3599   Upon return, *info has been modified to only contain the driver files
3600   which are not in use
3601 ****************************************************************************/
3602
3603 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
3604 {
3605         int                             i;
3606         int                             ndrivers;
3607         uint32                          version;
3608         fstring                         *list = NULL;
3609         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
3610         
3611         /* loop over all driver versions */
3612         
3613         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
3614         
3615         for ( version=0; version<DRIVER_MAX_VERSION; version++ )
3616         {
3617                 /* get the list of drivers */
3618                 
3619                 list = NULL;
3620                 ndrivers = get_ntdrivers(&list, info->environment, version);
3621                 
3622                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
3623                         ndrivers, info->environment, version));
3624
3625                 if (ndrivers == -1)
3626                         continue;
3627                         
3628                 /* check each driver for overlap in files */
3629                 
3630                 for (i=0; i<ndrivers; i++) 
3631                 {
3632                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
3633                         
3634                         ZERO_STRUCT(driver);
3635                         
3636                         if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], 
3637                                 info->environment, version)) )
3638                         {
3639                                 SAFE_FREE(list);
3640                                 return True;
3641                         }
3642                         
3643                         /* check if d2 uses any files from d1 */
3644                         /* only if this is a different driver than the one being deleted */
3645                         
3646                         if ( !strequal(info->name, driver.info_3->name) 
3647                                 || (info->cversion != driver.info_3->cversion) )
3648                         {
3649                                 if ( trim_overlap_drv_files(info, driver.info_3) ) {
3650                                         free_a_printer_driver(driver, 3);
3651                                         SAFE_FREE( list );
3652                                         return True;
3653                                 }
3654                         }
3655         
3656                         free_a_printer_driver(driver, 3);
3657                 }       
3658                 
3659                 SAFE_FREE(list);
3660         }
3661         
3662         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
3663         
3664         return False;
3665 }
3666
3667 /****************************************************************************
3668   Actually delete the driver files.  Make sure that 
3669   printer_driver_files_in_use() return False before calling 
3670   this.
3671 ****************************************************************************/
3672
3673 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user )
3674 {
3675         char *s;
3676         connection_struct *conn;
3677         DATA_BLOB null_pw;
3678         NTSTATUS nt_status;
3679         
3680         if ( !i )
3681                 return False;
3682                 
3683         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", i->name, i->cversion));
3684         
3685         /*
3686          * Connect to the print$ share under the same account as the 
3687          * user connected to the rpc pipe. Note we must be root to 
3688          * do this.
3689          */
3690          
3691         become_root();
3692         null_pw = data_blob( NULL, 0 );
3693         conn = make_connection_with_chdir( "print$", null_pw, "A:", user->vuid, &nt_status );
3694         unbecome_root();
3695         
3696         if ( !conn ) {
3697                 DEBUG(0,("delete_driver_files: Unable to connect\n"));
3698                 return False;
3699         }
3700
3701         /* Save who we are - we are temporarily becoming the connection user. */
3702
3703         if ( !become_user(conn, conn->vuid) ) {
3704                 DEBUG(0,("delete_driver_files: Can't become user!\n"));
3705                 return False;
3706         }
3707
3708         /* now delete the files; must strip the '\print$' string from 
3709            fron of path                                                */
3710         
3711         if ( *i->driverpath ) {
3712                 if ( (s = strchr( &i->driverpath[1], '\\' )) != NULL ) {
3713                         DEBUG(10,("deleting driverfile [%s]\n", s));
3714                         unlink_internals(conn, 0, s);
3715                 }
3716         }
3717                 
3718         if ( *i->configfile ) {
3719                 if ( (s = strchr( &i->configfile[1], '\\' )) != NULL ) {
3720                         DEBUG(10,("deleting configfile [%s]\n", s));
3721                         unlink_internals(conn, 0, s);
3722                 }
3723         }
3724         
3725         if ( *i->datafile ) {
3726                 if ( (s = strchr( &i->datafile[1], '\\' )) != NULL ) {
3727                         DEBUG(10,("deleting datafile [%s]\n", s));
3728                         unlink_internals(conn, 0, s);
3729                 }
3730         }
3731         
3732         if ( *i->helpfile ) {
3733                 if ( (s = strchr( &i->helpfile[1], '\\' )) != NULL ) {
3734                         DEBUG(10,("deleting helpfile [%s]\n", s));
3735                         unlink_internals(conn, 0, s);
3736                 }
3737         }
3738         
3739         s = (char*)i->dependentfiles;
3740         
3741         while ( s && *s ) {
3742                 char *file;
3743
3744                 if ( (file = strchr( s+1, '\\' )) != NULL )
3745                 {
3746                         DEBUG(10,("deleting dependent file [%s]\n", file));
3747                         unlink_internals(conn, 0, file );
3748                         file += strlen( file ) + 1;
3749                 }
3750
3751                 s = file;
3752         }
3753
3754         return True;
3755 }
3756
3757 /****************************************************************************
3758  Remove a printer driver from the TDB.  This assumes that the the driver was
3759  previously looked up.
3760  ***************************************************************************/
3761
3762 static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user,
3763                               uint32 version, BOOL delete_files )
3764 {
3765         pstring         key;
3766         fstring         arch;
3767         TDB_DATA        kbuf, dbuf;
3768         NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
3769
3770         /* delete the tdb data first */
3771
3772         get_short_archi(arch, i->environment);
3773         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
3774                 arch, version, i->name);
3775
3776         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
3777                 key, delete_files ? "TRUE" : "FALSE" ));
3778
3779         ctr.info_3 = i;
3780         dump_a_printer_driver( ctr, 3 );
3781
3782         kbuf.dptr=key;
3783         kbuf.dsize=strlen(key)+1;
3784
3785         /* check if the driver actually exists for this environment */
3786         
3787         dbuf = tdb_fetch( tdb_drivers, kbuf );
3788         if ( !dbuf.dptr ) {
3789                 DEBUG(8,("delete_printer_driver_internal: Driver unknown [%s]\n", key));
3790                 return WERR_UNKNOWN_PRINTER_DRIVER;
3791         }
3792                 
3793         SAFE_FREE( dbuf.dptr );
3794         
3795         /* ok... the driver exists so the delete should return success */
3796                 
3797         if (tdb_delete(tdb_drivers, kbuf) == -1) {
3798                 DEBUG (0,("delete_printer_driver_internal: fail to delete %s!\n", key));
3799                 return WERR_ACCESS_DENIED;
3800         }
3801
3802         /*
3803          * now delete any associated files if delete_files == True
3804          * even if this part failes, we return succes because the
3805          * driver doesn not exist any more
3806          */
3807
3808         if ( delete_files )
3809                 delete_driver_files( i, user );
3810
3811
3812         DEBUG(5,("delete_printer_driver_internal: driver delete successful [%s]\n", key));
3813
3814         return WERR_OK;
3815 }
3816
3817 /****************************************************************************
3818  Remove a printer driver from the TDB.  This assumes that the the driver was
3819  previously looked up.
3820  ***************************************************************************/
3821
3822 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user,
3823                               uint32 version, BOOL delete_files )
3824 {
3825         WERROR err;
3826
3827         /*
3828          * see if we should delete all versions of this driver 
3829          * (DRIVER_ANY_VERSION uis only set for "Windows NT x86")
3830          */
3831
3832         if ( version == DRIVER_ANY_VERSION ) 
3833         {
3834                 /* Windows NT 4.0 */
3835                 
3836                 err = delete_printer_driver_internal(i, user, 2, delete_files );
3837                 if ( !W_ERROR_IS_OK(err) && (W_ERROR_V(err) != ERRunknownprinterdriver ) )
3838                         return err;
3839                         
3840                 /* Windows 2000/XP  */
3841                 
3842                 err = delete_printer_driver_internal(i, user, 3, delete_files );
3843                 if ( !W_ERROR_IS_OK(err) && (W_ERROR_V(err) != ERRunknownprinterdriver ) )
3844                                 return err;
3845
3846         return WERR_OK;
3847         }
3848         
3849         /* just delete what they asked for */
3850         
3851         return delete_printer_driver_internal(i, user, version, delete_files );
3852 }
3853
3854
3855 /****************************************************************************
3856 ****************************************************************************/
3857
3858 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
3859                                  fstring value, uint8 **data, uint32 *type, uint32 *len)
3860 {
3861         /* right now that's enough ! */
3862         NT_PRINTER_PARAM *param;
3863         int i=0;
3864         
3865         param=printer.info_2->specific;
3866         
3867         while (param != NULL && i < param_index) {
3868                 param=param->next;
3869                 i++;
3870         }
3871         
3872         if (param == NULL)
3873                 return False;
3874
3875         /* exited because it exist */
3876         *type=param->type;              
3877         StrnCpy(value, param->value, sizeof(fstring)-1);
3878         *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3879         if(*data == NULL)
3880                 return False;
3881         ZERO_STRUCTP(*data);
3882         memcpy(*data, param->data, param->data_len);
3883         *len=param->data_len;
3884         return True;
3885 }
3886
3887 /****************************************************************************
3888 ****************************************************************************/
3889 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
3890                         fstring value, uint8 **data, uint32 *type, uint32 *len)
3891 {
3892         /* right now that's enough ! */ 
3893         NT_PRINTER_PARAM *param;
3894         
3895         DEBUG(10, ("get_specific_param\n"));
3896         
3897         param=printer.info_2->specific;
3898                 
3899         while (param != NULL)
3900         {
3901 #if 1 /* JRA - I think this should be case insensitive.... */
3902                 if ( strequal(value, param->value)
3903 #else
3904                 if ( !strcmp(value, param->value)
3905 #endif
3906                     && strlen(value)==strlen(param->value))
3907                         break;
3908                         
3909                 param=param->next;
3910         }
3911         
3912         if (param != NULL)
3913         {
3914         DEBUGADD(10, ("get_specific_param: found one param\n"));
3915                 /* exited because it exist */
3916                 *type=param->type;      
3917                 
3918                 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3919                 if(*data == NULL)
3920                         return False;
3921                 memcpy(*data, param->data, param->data_len);
3922                 *len=param->data_len;
3923
3924                 DEBUGADD(10, ("get_specific_param: exit true\n"));
3925                 return (True);
3926         }
3927         DEBUGADD(10, ("get_specific_param: exit false\n"));
3928         return (False);
3929 }
3930
3931 /****************************************************************************
3932  Store a security desc for a printer.
3933 ****************************************************************************/
3934
3935 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
3936 {
3937         SEC_DESC_BUF *new_secdesc_ctr = NULL;
3938         SEC_DESC_BUF *old_secdesc_ctr = NULL;
3939         prs_struct ps;
3940         TALLOC_CTX *mem_ctx = NULL;
3941         fstring key;
3942         WERROR status;
3943
3944         mem_ctx = talloc_init();
3945         if (mem_ctx == NULL)
3946                 return WERR_NOMEM;
3947
3948         /* The old owner and group sids of the security descriptor are not
3949            present when new ACEs are added or removed by changing printer
3950            permissions through NT.  If they are NULL in the new security
3951            descriptor then copy them over from the old one. */
3952
3953         if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3954                 DOM_SID *owner_sid, *group_sid;
3955                 SEC_ACL *dacl, *sacl;
3956                 SEC_DESC *psd = NULL;
3957                 size_t size;
3958
3959                 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3960
3961                 /* Pick out correct owner and group sids */
3962
3963                 owner_sid = secdesc_ctr->sec->owner_sid ?
3964                         secdesc_ctr->sec->owner_sid :
3965                         old_secdesc_ctr->sec->owner_sid;
3966
3967                 group_sid = secdesc_ctr->sec->grp_sid ?
3968                         secdesc_ctr->sec->grp_sid :
3969                         old_secdesc_ctr->sec->grp_sid;
3970
3971                 dacl = secdesc_ctr->sec->dacl ?
3972                         secdesc_ctr->sec->dacl :
3973                         old_secdesc_ctr->sec->dacl;
3974
3975                 sacl = secdesc_ctr->sec->sacl ?
3976                         secdesc_ctr->sec->sacl :
3977                         old_secdesc_ctr->sec->sacl;
3978
3979                 /* Make a deep copy of the security descriptor */
3980
3981                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3982                                     owner_sid, group_sid,
3983                                     sacl,
3984                                     dacl,
3985                                     &size);
3986
3987                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3988         }
3989
3990         if (!new_secdesc_ctr) {
3991                 new_secdesc_ctr = secdesc_ctr;
3992         }
3993
3994         /* Store the security descriptor in a tdb */
3995
3996         prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3997                  sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3998
3999         if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4000                              &ps, 1)) {
4001                 status = WERR_BADFUNC;
4002                 goto out;
4003         }
4004
4005         slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4006
4007         if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4008                 status = WERR_OK;
4009         } else {
4010                 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4011                 status = WERR_BADFUNC;
4012         }
4013
4014         /* Free malloc'ed memory */
4015
4016  out:
4017
4018         prs_mem_free(&ps);
4019         if (mem_ctx)
4020                 talloc_destroy(mem_ctx);
4021         return status;
4022 }
4023
4024 /****************************************************************************
4025  Construct a default security descriptor buffer for a printer.
4026 ****************************************************************************/
4027
4028 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4029 {
4030         SEC_ACE ace[3];
4031         SEC_ACCESS sa;
4032         SEC_ACL *psa = NULL;
4033         SEC_DESC_BUF *sdb = NULL;
4034         SEC_DESC *psd = NULL;
4035         DOM_SID owner_sid;
4036         size_t sd_size;
4037
4038         /* Create an ACE where Everyone is allowed to print */
4039
4040         init_sec_access(&sa, PRINTER_ACE_PRINT);
4041         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4042                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4043
4044         /* Make the security descriptor owned by the Administrators group
4045            on the PDC of the domain. */
4046
4047         if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4048                 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4049         } else {
4050
4051                 /* Backup plan - make printer owned by admins.
4052                    This should emulate a lanman printer as security
4053                    settings can't be changed. */
4054
4055                 sid_copy(&owner_sid, get_global_sam_sid());
4056                 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4057         }
4058
4059         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4060         init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4061                      sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4062                      SEC_ACE_FLAG_INHERIT_ONLY);
4063
4064         init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4065         init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4066                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4067
4068         /* The ACL revision number in rpc_secdesc.h differs from the one
4069            created by NT when setting ACE entries in printer
4070            descriptors.  NT4 complains about the property being edited by a
4071            NT5 machine. */
4072
4073         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4074                 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
4075                                     &owner_sid, NULL,
4076                                     NULL, psa, &sd_size);
4077         }
4078
4079         if (!psd) {
4080                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4081                 return NULL;
4082         }
4083
4084         sdb = make_sec_desc_buf(ctx, sd_size, psd);
4085
4086         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4087                  (unsigned int)sd_size));
4088
4089         return sdb;
4090 }
4091
4092 /****************************************************************************
4093  Get a security desc for a printer.
4094 ****************************************************************************/
4095
4096 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4097 {
4098         prs_struct ps;
4099         fstring key;
4100         char *temp;
4101
4102         if ((temp = strchr(printername + 2, '\\'))) {
4103                 printername = temp + 1;
4104         }
4105
4106         /* Fetch security descriptor from tdb */
4107
4108         slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4109
4110         if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4111             !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4112
4113                 DEBUG(4,("using default secdesc for %s\n", printername));
4114
4115                 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4116                         return False;
4117                 }
4118
4119                 /* Save default security descriptor for later */
4120
4121                 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4122                                 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4123
4124                 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4125                         tdb_prs_store(tdb_printers, key, &ps);
4126
4127                 prs_mem_free(&ps);
4128
4129                 return True;
4130         }
4131
4132         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4133            this security descriptor has been created when winbindd was
4134            down.  Take ownership of security descriptor. */
4135
4136         if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4137                 DOM_SID owner_sid;
4138
4139                 /* Change sd owner to workgroup administrator */
4140
4141                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4142                         SEC_DESC_BUF *new_secdesc_ctr = NULL;
4143                         SEC_DESC *psd = NULL;
4144                         size_t size;
4145
4146                         /* Create new sd */
4147
4148                         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4149
4150                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
4151                                             &owner_sid,
4152                                             (*secdesc_ctr)->sec->grp_sid,
4153                                             (*secdesc_ctr)->sec->sacl,
4154                                             (*secdesc_ctr)->sec->dacl,
4155                                             &size);
4156
4157                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4158
4159                         /* Swap with other one */
4160
4161                         *secdesc_ctr = new_secdesc_ctr;
4162
4163                         /* Set it */
4164
4165                         nt_printing_setsec(printername, *secdesc_ctr);
4166                 }
4167         }
4168
4169         if (DEBUGLEVEL >= 10) {
4170                 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4171                 int i;
4172
4173                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
4174                            printername, the_acl->num_aces));
4175
4176                 for (i = 0; i < the_acl->num_aces; i++) {
4177                         fstring sid_str;
4178
4179                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
4180
4181                         DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4182                                    the_acl->ace[i].type, the_acl->ace[i].flags, 
4183                                    the_acl->ace[i].info.mask)); 
4184                 }
4185         }
4186
4187         prs_mem_free(&ps);
4188         return True;
4189 }
4190
4191 /* error code:
4192         0: everything OK
4193         1: level not implemented
4194         2: file doesn't exist
4195         3: can't allocate memory
4196         4: can't free memory
4197         5: non existant struct
4198 */
4199
4200 /*
4201         A printer and a printer driver are 2 different things.
4202         NT manages them separatelly, Samba does the same.
4203         Why ? Simply because it's easier and it makes sense !
4204         
4205         Now explanation: You have 3 printers behind your samba server,
4206         2 of them are the same make and model (laser A and B). But laser B
4207         has an 3000 sheet feeder and laser A doesn't such an option.
4208         Your third printer is an old dot-matrix model for the accounting :-).
4209         
4210         If the /usr/local/samba/lib directory (default dir), you will have
4211         5 files to describe all of this.
4212         
4213         3 files for the printers (1 by printer):
4214                 NTprinter_laser A
4215                 NTprinter_laser B
4216                 NTprinter_accounting
4217         2 files for the drivers (1 for the laser and 1 for the dot matrix)
4218                 NTdriver_printer model X
4219                 NTdriver_printer model Y
4220
4221 jfm: I should use this comment for the text file to explain
4222         same thing for the forms BTW.
4223         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4224
4225 */
4226
4227 /* Convert generic access rights to printer object specific access rights.
4228    It turns out that NT4 security descriptors use generic access rights and
4229    NT5 the object specific ones. */
4230
4231 void map_printer_permissions(SEC_DESC *sd)
4232 {
4233         int i;
4234
4235         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4236                 se_map_generic(&sd->dacl->ace[i].info.mask,
4237                                &printer_generic_mapping);
4238         }
4239 }
4240
4241 /****************************************************************************
4242  Check a user has permissions to perform the given operation.  We use the
4243  permission constants defined in include/rpc_spoolss.h to check the various
4244  actions we perform when checking printer access.
4245
4246    PRINTER_ACCESS_ADMINISTER:
4247        print_queue_pause, print_queue_resume, update_printer_sec,
4248        update_printer, spoolss_addprinterex_level_2,
4249        _spoolss_setprinterdata
4250
4251    PRINTER_ACCESS_USE:
4252        print_job_start
4253
4254    JOB_ACCESS_ADMINISTER:
4255        print_job_delete, print_job_pause, print_job_resume,
4256        print_queue_purge
4257
4258  ****************************************************************************/
4259 BOOL print_access_check(struct current_user *user, int snum, int access_type)
4260 {
4261         SEC_DESC_BUF *secdesc = NULL;
4262         uint32 access_granted;
4263         NTSTATUS status;
4264         BOOL result;
4265         const char *pname;
4266         TALLOC_CTX *mem_ctx = NULL;
4267         extern struct current_user current_user;
4268         
4269         /* If user is NULL then use the current_user structure */
4270
4271         if (!user)
4272                 user = &current_user;
4273
4274         /* Always allow root or printer admins to do anything */
4275
4276         if (user->uid == 0 ||
4277             user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
4278                 return True;
4279         }
4280
4281         /* Get printer name */
4282
4283         pname = PRINTERNAME(snum);
4284
4285         if (!pname || !*pname) {
4286                 errno = EACCES;
4287                 return False;
4288         }
4289
4290         /* Get printer security descriptor */
4291
4292         if(!(mem_ctx = talloc_init())) {
4293                 errno = ENOMEM;
4294                 return False;
4295         }
4296
4297         nt_printing_getsec(mem_ctx, pname, &secdesc);
4298
4299         if (access_type == JOB_ACCESS_ADMINISTER) {
4300                 SEC_DESC_BUF *parent_secdesc = secdesc;
4301
4302                 /* Create a child security descriptor to check permissions
4303                    against.  This is because print jobs are child objects
4304                    objects of a printer. */
4305
4306                 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4307
4308                 /* Now this is the bit that really confuses me.  The access
4309                    type needs to be changed from JOB_ACCESS_ADMINISTER to
4310                    PRINTER_ACCESS_ADMINISTER for this to work.  Something
4311                    to do with the child (job) object becoming like a
4312                    printer??  -tpot */
4313
4314                 access_type = PRINTER_ACCESS_ADMINISTER;
4315         }
4316         
4317         /* Check access */
4318         
4319         map_printer_permissions(secdesc->sec);
4320
4321         result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4322                                  &access_granted, &status);
4323
4324         DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4325
4326         talloc_destroy(mem_ctx);
4327         
4328         if (!result)
4329                 errno = EACCES;
4330
4331         return result;
4332 }
4333
4334 /****************************************************************************
4335  Check the time parameters allow a print operation.
4336 *****************************************************************************/
4337
4338 BOOL print_time_access_check(int snum)
4339 {
4340         NT_PRINTER_INFO_LEVEL *printer = NULL;
4341         BOOL ok = False;
4342         time_t now = time(NULL);
4343         struct tm *t;
4344         uint32 mins;
4345
4346         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4347                 return False;
4348
4349         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
4350                 ok = True;
4351
4352         t = gmtime(&now);
4353         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4354
4355         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
4356                 ok = True;
4357
4358         free_a_printer(&printer, 2);
4359
4360         if (!ok)
4361                 errno = EACCES;
4362
4363         return ok;
4364 }
4365
4366 #if 0   /* JERRY - not used */
4367 /****************************************************************************
4368  Attempt to write a default device.
4369 *****************************************************************************/
4370
4371 WERROR printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
4372 {
4373         NT_PRINTER_INFO_LEVEL *printer = NULL;
4374         WERROR result;
4375
4376         /*
4377          * Don't bother if no default devicemode was sent.
4378          */
4379
4380         if (printer_default->devmode_cont.devmode == NULL)
4381                 return WERR_OK;
4382
4383         result = get_a_printer(&printer, 2, lp_servicename(snum));
4384         if (!W_ERROR_IS_OK(result)) return result;
4385
4386         /*
4387          * Just ignore it if we already have a devmode.
4388          */
4389 #if 0
4390         if (printer->info_2->devmode != NULL)
4391                 goto done;
4392 #endif
4393         /*
4394          * We don't have a devicemode and we're trying to write
4395          * one. Check we have the access needed.
4396          */
4397         DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
4398
4399         if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) != 
4400               PRINTER_ACCESS_ADMINISTER) {
4401                 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
4402                 result = WERR_ACCESS_DENIED;
4403                 goto done;
4404         }
4405
4406         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4407                 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
4408                         lp_servicename(snum) ));
4409                 result = WERR_ACCESS_DENIED;
4410                 /*result = NT_STATUS_NO_PROBLEMO;*/
4411                 goto done;
4412         }
4413
4414         DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
4415
4416         /*
4417          * Convert the on the wire devicemode format to the internal one.
4418          */
4419
4420         if (!convert_devicemode(printer->info_2->printername,
4421                                 printer_default->devmode_cont.devmode,
4422                                 &printer->info_2->devmode)) {
4423                 result = WERR_NOMEM;
4424                 goto done;
4425         }
4426
4427         /*
4428          * Finally write back to the tdb.
4429          */
4430
4431         result = mod_a_printer(*printer, 2);
4432
4433   done:
4434
4435         free_a_printer(&printer, 2);
4436         return result;
4437 }
4438 #endif  /* JERRY */