d1ab5ce21d1abb2778948b0a8b000701ae153c53
[ira/wip.git] / source3 / printing / nt_printing.c
1 /*
2  *  Unix SMB/Netbios implementation.
3  *  Version 1.9.
4  *  RPC Pipe client / server routines
5  *  Copyright (C) Andrew Tridgell              1992-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000.
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  
37 #define NTDRIVERS_DATABASE_VERSION_1 1
38 #define NTDRIVERS_DATABASE_VERSION_2 2
39 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
40  
41 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
42
43 /* Map generic permissions to printer object specific permissions */
44
45 struct generic_mapping printer_generic_mapping = {
46         PRINTER_READ,
47         PRINTER_WRITE,
48         PRINTER_EXECUTE,
49         PRINTER_ALL_ACCESS
50 };
51
52 /* We need one default form to support our default printer. Msoft adds the
53 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
54 array index). Letter is always first, so (for the current code) additions
55 always put things in the correct order. */
56 static nt_forms_struct default_forms[] = {
57         {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
58         {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
59         {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
60         {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
61         {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
62         {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
63         {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
64         {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
65         {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
66         {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
67         {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
68         {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
69         {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
70         {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
71         {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
72         {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
73         {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
74         {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
75         {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
76         {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
77         {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
78         {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
79         {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
80         {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
81         {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
82         {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
83         {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
84         {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
85         {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
86         {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
87         {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
88         {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
89         {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
90         {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
91         {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
92         {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
93         {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
94         {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
95         {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
96         {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
97         {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
98         {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
99         {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
100         {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
101         {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
102         {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
103         {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
104         {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
105         {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
106         {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
107         {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
108         {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
109         {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
110         {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
111         {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
112         {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
113         {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
114         {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
115         {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
116         {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
117         {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
118         {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
119         {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
120         {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
121         {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
122         {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
123         {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
124         {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
125         {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
126         {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
127         {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
128         {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
129         {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
130         {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
131         {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
132         {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
133         {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
134         {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
135         {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
136         {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
137         {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
138         {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
139         {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
140         {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
141         {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
142         {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
143         {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
144         {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
145         {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
146         {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
147         {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
148         {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
149         {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
150         {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
151         {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
152         {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
153         {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
154         {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
155         {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
156         {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
157         {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
158         {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
159         {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
160         {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
161         {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
162         {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
163         {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
164         {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
165         {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
166         {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
167         {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
168         {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
169         {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
170         {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
171         {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
172         {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
173         {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
174         {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
175 };
176
177 static BOOL upgrade_to_version_3(void)
178 {
179         TDB_DATA kbuf, newkey, dbuf;
180  
181         DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
182  
183         for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
184                         newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
185
186                 dbuf = tdb_fetch(tdb_drivers, kbuf);
187
188                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
189                         DEBUG(0,("upgrade_to_version_3:moving form\n"));
190                         if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
191                                 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
192                                 return False;
193                         }
194                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
195                                 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
196                                 return False;
197                         }
198                 }
199  
200                 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
201                         DEBUG(0,("upgrade_to_version_3:moving printer\n"));
202                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
203                                 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
204                                 return False;
205                         }
206                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
207                                 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
208                                 return False;
209                         }
210                 }
211  
212                 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
213                         DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
214                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
215                                 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
216                                 return False;
217                         }
218                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
219                                 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
220                                 return False;
221                         }
222                 }
223  
224                 SAFE_FREE(dbuf.dptr);
225         }
226
227         return True;
228 }
229
230 /****************************************************************************
231  Open the NT printing tdb.
232 ****************************************************************************/
233
234 BOOL nt_printing_init(void)
235 {
236         static pid_t local_pid;
237         char *vstring = "INFO/version";
238
239         if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
240                 return True;
241  
242         tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
243         if (!tdb_drivers) {
244                 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
245                         lock_path("ntdrivers.tdb"), strerror(errno) ));
246                 return False;
247         }
248  
249         tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
250         if (!tdb_printers) {
251                 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
252                         lock_path("ntprinters.tdb"), strerror(errno) ));
253                 return False;
254         }
255  
256         tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
257         if (!tdb_forms) {
258                 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
259                         lock_path("ntforms.tdb"), strerror(errno) ));
260                 return False;
261         }
262  
263         local_pid = sys_getpid();
264  
265         /* handle a Samba upgrade */
266         tdb_lock_bystring(tdb_drivers, vstring);
267         {
268                 int32 vers_id;
269
270                 /* Cope with byte-reversed older versions of the db. */
271                 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
272                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
273                         /* Written on a bigendian machine with old fetch_int code. Save as le. */
274                         /* The only upgrade between V2 and V3 is to save the version in little-endian. */
275                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
276                         vers_id = NTDRIVERS_DATABASE_VERSION;
277                 }
278
279                 if (vers_id != NTDRIVERS_DATABASE_VERSION) {
280  
281                         if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
282                                 if (!upgrade_to_version_3())
283                                         return False;
284                         } else
285                                 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
286
287                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
288                 }
289         }
290         tdb_unlock_bystring(tdb_drivers, vstring);
291
292         return True;
293 }
294
295 /****************************************************************************
296  get builtin form struct list
297 ****************************************************************************/
298 int get_builtin_ntforms(nt_forms_struct **list)
299 {
300         *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
301         return sizeof(default_forms) / sizeof(default_forms[0]);
302 }
303
304 /****************************************************************************
305  get a builtin form struct
306 ****************************************************************************/
307
308 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
309 {
310         int i,count;
311         fstring form_name;
312         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
313         DEBUGADD(6,("Looking for builtin form %s \n", form_name));
314         count = sizeof(default_forms) / sizeof(default_forms[0]);
315         for (i=0;i<count;i++) {
316                 if (strequal(form_name,default_forms[i].name)) {
317                         DEBUGADD(6,("Found builtin form %s \n", form_name));
318                         memcpy(form,&default_forms[i],sizeof(*form));
319                         break;
320                 }
321         }
322
323         return (i !=count);
324 }
325
326 /****************************************************************************
327 get a form struct list
328 ****************************************************************************/
329 int get_ntforms(nt_forms_struct **list)
330 {
331         TDB_DATA kbuf, newkey, dbuf;
332         nt_forms_struct *tl;
333         nt_forms_struct form;
334         int ret;
335         int i;
336         int n = 0;
337
338         for (kbuf = tdb_firstkey(tdb_forms);
339              kbuf.dptr;
340              newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
341                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
342                 
343                 dbuf = tdb_fetch(tdb_forms, kbuf);
344                 if (!dbuf.dptr) continue;
345
346                 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
347                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
348                                  &i, &form.flag, &form.width, &form.length, &form.left,
349                                  &form.top, &form.right, &form.bottom);
350                 SAFE_FREE(dbuf.dptr);
351                 if (ret != dbuf.dsize) continue;
352
353                 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
354                 if (!tl) {
355                         DEBUG(0,("get_ntforms: Realloc fail.\n"));
356                         return 0;
357                 }
358                 *list = tl;
359                 (*list)[n] = form;
360                 n++;
361         }
362         
363
364         return n;
365 }
366
367 /****************************************************************************
368 write a form struct list
369 ****************************************************************************/
370 int write_ntforms(nt_forms_struct **list, int number)
371 {
372         pstring buf, key;
373         int len;
374         TDB_DATA kbuf,dbuf;
375         int i;
376
377         for (i=0;i<number;i++) {
378                 /* save index, so list is rebuilt in correct order */
379                 len = tdb_pack(buf, sizeof(buf), "dddddddd",
380                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
381                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
382                                (*list)[i].bottom);
383                 if (len > sizeof(buf)) break;
384                 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
385                 kbuf.dsize = strlen(key)+1;
386                 kbuf.dptr = key;
387                 dbuf.dsize = len;
388                 dbuf.dptr = buf;
389                 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
390        }
391
392        return i;
393 }
394
395 /****************************************************************************
396 add a form struct at the end of the list
397 ****************************************************************************/
398 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
399 {
400         int n=0;
401         BOOL update;
402         fstring form_name;
403         nt_forms_struct *tl;
404
405         /*
406          * NT tries to add forms even when
407          * they are already in the base
408          * only update the values if already present
409          */
410
411         update=False;
412         
413         unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
414         for (n=0; n<*count; n++) {
415                 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
416                         DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
417                         update=True;
418                         break;
419                 }
420         }
421
422         if (update==False) {
423                 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
424                         DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
425                         return False;
426                 }
427                 *list = tl;
428                 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
429                 (*count)++;
430         }
431         
432         (*list)[n].flag=form->flags;
433         (*list)[n].width=form->size_x;
434         (*list)[n].length=form->size_y;
435         (*list)[n].left=form->left;
436         (*list)[n].top=form->top;
437         (*list)[n].right=form->right;
438         (*list)[n].bottom=form->bottom;
439
440         return True;
441 }
442
443 /****************************************************************************
444  delete a named form struct
445 ****************************************************************************/
446 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
447 {
448         pstring key;
449         TDB_DATA kbuf;
450         int n=0;
451         fstring form_name;
452
453         *ret = WERR_OK;
454
455         unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
456
457         for (n=0; n<*count; n++) {
458                 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
459                         DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
460                         break;
461                 }
462         }
463
464         if (n == *count) {
465                 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
466                 *ret = WERR_INVALID_PARAM;
467                 return False;
468         }
469
470         slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
471         kbuf.dsize = strlen(key)+1;
472         kbuf.dptr = key;
473         if (tdb_delete(tdb_forms, kbuf) != 0) {
474                 *ret = WERR_NOMEM;
475                 return False;
476         }
477
478         return True;
479 }
480
481 /****************************************************************************
482 update a form struct
483 ****************************************************************************/
484 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
485 {
486         int n=0;
487         fstring form_name;
488         unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
489
490         DEBUG(106, ("[%s]\n", form_name));
491         for (n=0; n<count; n++)
492         {
493                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
494                 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
495                         break;
496         }
497
498         if (n==count) return;
499
500         (*list)[n].flag=form->flags;
501         (*list)[n].width=form->size_x;
502         (*list)[n].length=form->size_y;
503         (*list)[n].left=form->left;
504         (*list)[n].top=form->top;
505         (*list)[n].right=form->right;
506         (*list)[n].bottom=form->bottom;
507 }
508
509 /****************************************************************************
510 get the nt drivers list
511
512 traverse the database and look-up the matching names
513 ****************************************************************************/
514 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
515 {
516         int total=0;
517         fstring short_archi;
518         fstring *fl;
519         pstring key;
520         TDB_DATA kbuf, newkey;
521
522         get_short_archi(short_archi, architecture);
523         slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
524
525         for (kbuf = tdb_firstkey(tdb_drivers);
526              kbuf.dptr;
527              newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
528                 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
529                 
530                 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
531                         DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
532                         return -1;
533                 }
534                 else *list = fl;
535
536                 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
537                 total++;
538         }
539
540         return(total);
541 }
542
543 /****************************************************************************
544 function to do the mapping between the long architecture name and
545 the short one.
546 ****************************************************************************/
547 BOOL get_short_archi(char *short_archi, char *long_archi)
548 {
549         struct table {
550                 char *long_archi;
551                 char *short_archi;
552         };
553         
554         struct table archi_table[]=
555         {
556                 {"Windows 4.0",          "WIN40"    },
557                 {"Windows NT x86",       "W32X86"   },
558                 {"Windows NT R4000",     "W32MIPS"  },
559                 {"Windows NT Alpha_AXP", "W32ALPHA" },
560                 {"Windows NT PowerPC",   "W32PPC"   },
561                 {NULL,                   ""         }
562         };
563         
564         int i=-1;
565
566         DEBUG(107,("Getting architecture dependant directory\n"));
567         do {
568                 i++;
569         } while ( (archi_table[i].long_archi!=NULL ) &&
570                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
571
572         if (archi_table[i].long_archi==NULL) {
573                 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
574                 return False;
575         }
576
577         StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
578
579         DEBUGADD(108,("index: [%d]\n", i));
580         DEBUGADD(108,("long architecture: [%s]\n", long_archi));
581         DEBUGADD(108,("short architecture: [%s]\n", short_archi));
582         
583         return True;
584 }
585
586 /****************************************************************************
587  Version information in Microsoft files is held in a VS_VERSION_INFO structure.
588  There are two case to be covered here: PE (Portable Executable) and NE (New
589  Executable) files. Both files support the same INFO structure, but PE files
590  store the signature in unicode, and NE files store it as !unicode.
591  returns -1 on error, 1 on version info found, and 0 on no version info found.
592 ****************************************************************************/
593
594 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
595 {
596         int     i;
597         char    *buf;
598         ssize_t byte_count;
599
600         if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
601                 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
602                                 fname, PE_HEADER_SIZE));
603                 goto error_exit;
604         }
605
606         /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
607         if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
608                 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
609                                 fname, byte_count));
610                 goto no_version_info;
611         }
612
613         /* Is this really a DOS header? */
614         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
615                 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
616                                 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
617                 goto no_version_info;
618         }
619
620         /* Skip OEM header (if any) and the DOS stub to start of Windows header */
621         if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
622                 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
623                                 fname, errno));
624                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
625                 goto no_version_info;
626         }
627
628         if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
629                 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
630                                 fname, byte_count));
631                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
632                 goto no_version_info;
633         }
634
635         /* The header may be a PE (Portable Executable) or an NE (New Executable) */
636         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
637                 int num_sections;
638                 int section_table_bytes;
639                 
640                 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
641                         DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
642                                         fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
643                         /* At this point, we assume the file is in error. It still could be somthing
644                          * else besides a PE file, but it unlikely at this point.
645                          */
646                         goto error_exit;
647                 }
648
649                 /* get the section table */
650                 num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
651                 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
652                 SAFE_FREE(buf);
653                 if ((buf=malloc(section_table_bytes)) == NULL) {
654                         DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
655                                         fname, section_table_bytes));
656                         goto error_exit;
657                 }
658
659                 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
660                         DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
661                                         fname, byte_count));
662                         goto error_exit;
663                 }
664
665                 /* Iterate the section table looking for the resource section ".rsrc" */
666                 for (i = 0; i < num_sections; i++) {
667                         int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
668
669                         if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
670                                 int section_pos   = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
671                                 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
672
673                                 SAFE_FREE(buf);
674                                 if ((buf=malloc(section_bytes)) == NULL) {
675                                         DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
676                                                         fname, section_bytes));
677                                         goto error_exit;
678                                 }
679
680                                 /* Seek to the start of the .rsrc section info */
681                                 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
682                                         DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
683                                                         fname, errno));
684                                         goto error_exit;
685                                 }
686
687                                 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
688                                         DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
689                                                         fname, byte_count));
690                                         goto error_exit;
691                                 }
692
693                                 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
694                                         /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
695                                         if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
696                                                 /* Align to next long address */
697                                                 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
698
699                                                 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
700                                                         *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
701                                                         *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
702                                                         
703                                                         DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
704                                                                           fname, *major, *minor,
705                                                                           (*major>>16)&0xffff, *major&0xffff,
706                                                                           (*minor>>16)&0xffff, *minor&0xffff));
707                                                         SAFE_FREE(buf);
708                                                         return 1;
709                                                 }
710                                         }
711                                 }
712                         }
713                 }
714
715                 /* Version info not found, fall back to origin date/time */
716                 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
717                 SAFE_FREE(buf);
718                 return 0;
719
720         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
721                 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
722                         DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
723                                         fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
724                         /* At this point, we assume the file is in error. It still could be somthing
725                          * else besides a NE file, but it unlikely at this point. */
726                         goto error_exit;
727                 }
728
729                 /* Allocate a bit more space to speed up things */
730                 SAFE_FREE(buf);
731                 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
732                         DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes  = %d\n",
733                                         fname, PE_HEADER_SIZE));
734                         goto error_exit;
735                 }
736
737                 /* This is a HACK! I got tired of trying to sort through the messy
738                  * 'NE' file format. If anyone wants to clean this up please have at
739                  * it, but this works. 'NE' files will eventually fade away. JRR */
740                 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
741                         /* Cover case that should not occur in a well formed 'NE' .dll file */
742                         if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
743
744                         for(i=0; i<byte_count; i++) {
745                                 /* Fast skip past data that can't possibly match */
746                                 if (buf[i] != 'V') continue;
747
748                                 /* Potential match data crosses buf boundry, move it to beginning
749                                  * of buf, and fill the buf with as much as it will hold. */
750                                 if (i>byte_count-VS_VERSION_INFO_SIZE) {
751                                         int bc;
752
753                                         memcpy(buf, &buf[i], byte_count-i);
754                                         if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
755                                                                    (byte_count-i))) < 0) {
756
757                                                 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
758                                                                  fname, errno));
759                                                 goto error_exit;
760                                         }
761
762                                         byte_count = bc + (byte_count - i);
763                                         if (byte_count<VS_VERSION_INFO_SIZE) break;
764
765                                         i = 0;
766                                 }
767
768                                 /* Check that the full signature string and the magic number that
769                                  * follows exist (not a perfect solution, but the chances that this
770                                  * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
771                                  * twice, as it is simpler to read the code. */
772                                 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
773                                         /* Compute skip alignment to next long address */
774                                         int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
775                                                                  sizeof(VS_SIGNATURE)) & 3;
776                                         if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
777
778                                         *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
779                                         *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
780                                         DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
781                                                           fname, *major, *minor,
782                                                           (*major>>16)&0xffff, *major&0xffff,
783                                                           (*minor>>16)&0xffff, *minor&0xffff));
784                                         SAFE_FREE(buf);
785                                         return 1;
786                                 }
787                         }
788                 }
789
790                 /* Version info not found, fall back to origin date/time */
791                 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
792                 SAFE_FREE(buf);
793                 return 0;
794
795         } else
796                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
797                 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
798                                 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
799
800         no_version_info:
801                 SAFE_FREE(buf);
802                 return 0;
803
804         error_exit:
805                 SAFE_FREE(buf);
806                 return -1;
807 }
808
809 /****************************************************************************
810 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
811 share one or more files. During the MS installation process files are checked
812 to insure that only a newer version of a shared file is installed over an
813 older version. There are several possibilities for this comparison. If there
814 is no previous version, the new one is newer (obviously). If either file is
815 missing the version info structure, compare the creation date (on Unix use
816 the modification date). Otherwise chose the numerically larger version number.
817 ****************************************************************************/
818 static int file_version_is_newer(connection_struct *conn, fstring new_file,
819                                                                 fstring old_file)
820 {
821         BOOL   use_version = True;
822         pstring filepath;
823
824         uint32 new_major;
825         uint32 new_minor;
826         time_t new_create_time;
827
828         uint32 old_major;
829         uint32 old_minor;
830         time_t old_create_time;
831
832         int access_mode;
833         int action;
834         files_struct    *fsp = NULL;
835         SMB_STRUCT_STAT st;
836         SMB_STRUCT_STAT stat_buf;
837         BOOL bad_path;
838
839         ZERO_STRUCT(st);
840         ZERO_STRUCT(stat_buf);
841         new_create_time = (time_t)0;
842         old_create_time = (time_t)0;
843
844         /* Get file version info (if available) for previous file (if it exists) */
845         pstrcpy(filepath, old_file);
846
847         unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
848
849         fsp = open_file_shared(conn, filepath, &stat_buf,
850                                                    SET_OPEN_MODE(DOS_OPEN_RDONLY),
851                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
852                                                    0, 0, &access_mode, &action);
853         if (!fsp) {
854                 /* Old file not found, so by definition new file is in fact newer */
855                 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
856                                 filepath, errno));
857                 return True;
858
859         } else {
860                 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
861                 if (ret == -1) goto error_exit;
862
863                 if (!ret) {
864                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
865                                          old_file));
866                         use_version = False;
867                         if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
868                         old_create_time = st.st_mtime;
869                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
870                 }
871         }
872         close_file(fsp, True);
873
874         /* Get file version info (if available) for new file */
875         pstrcpy(filepath, new_file);
876         unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
877
878         fsp = open_file_shared(conn, filepath, &stat_buf,
879                                                    SET_OPEN_MODE(DOS_OPEN_RDONLY),
880                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
881                                                    0, 0, &access_mode, &action);
882         if (!fsp) {
883                 /* New file not found, this shouldn't occur if the caller did its job */
884                 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
885                                 filepath, errno));
886                 goto error_exit;
887
888         } else {
889                 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
890                 if (ret == -1) goto error_exit;
891
892                 if (!ret) {
893                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
894                                          new_file));
895                         use_version = False;
896                         if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
897                         new_create_time = st.st_mtime;
898                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
899                 }
900         }
901         close_file(fsp, True);
902
903         if (use_version) {
904                 /* Compare versions and choose the larger version number */
905                 if (new_major > old_major ||
906                         (new_major == old_major && new_minor > old_minor)) {
907                         
908                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
909                         return True;
910                 }
911                 else {
912                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
913                         return False;
914                 }
915
916         } else {
917                 /* Compare modification time/dates and choose the newest time/date */
918                 if (new_create_time > old_create_time) {
919                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
920                         return True;
921                 }
922                 else {
923                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
924                         return False;
925                 }
926         }
927
928         error_exit:
929                 if(fsp)
930                         close_file(fsp, True);
931                 return -1;
932 }
933
934 /****************************************************************************
935 Determine the correct cVersion associated with an architecture and driver
936 ****************************************************************************/
937 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
938                                    struct current_user *user, WERROR *perr)
939 {
940         int               cversion;
941         int               access_mode;
942         int               action;
943         NTSTATUS          nt_status;
944         pstring           driverpath;
945         DATA_BLOB         null_pw;
946         files_struct      *fsp = NULL;
947         BOOL              bad_path;
948         SMB_STRUCT_STAT   st;
949         connection_struct *conn;
950
951         ZERO_STRUCT(st);
952
953         *perr = WERR_INVALID_PARAM;
954
955         /* If architecture is Windows 95/98/ME, the version is always 0. */
956         if (strcmp(architecture, "WIN40") == 0) {
957                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
958                 *perr = WERR_OK;
959                 return 0;
960         }
961
962         /* connect to the print$ share under the same account as the user connected to the rpc pipe */  
963         /* Null password is ok - we are already an authenticated user... */
964         null_pw = data_blob(NULL, 0);
965
966         become_root();
967         conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
968         unbecome_root();
969
970         if (conn == NULL) {
971                 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
972                 *perr = ntstatus_to_werror(nt_status);
973                 return -1;
974         }
975
976         /* We are temporarily becoming the connection user. */
977         if (!become_user(conn, conn->vuid)) {
978                 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
979                 *perr = WERR_ACCESS_DENIED;
980                 return -1;
981         }
982
983         /* Open the driver file (Portable Executable format) and determine the
984          * deriver the cversion. */
985         slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
986
987         unix_convert(driverpath,conn,NULL,&bad_path,&st);
988
989         fsp = open_file_shared(conn, driverpath, &st,
990                                                    SET_OPEN_MODE(DOS_OPEN_RDONLY),
991                                                    (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
992                                                    0, 0, &access_mode, &action);
993         if (!fsp) {
994                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
995                                 driverpath, errno));
996                 *perr = WERR_ACCESS_DENIED;
997                 goto error_exit;
998         }
999         else {
1000                 uint32 major;
1001                 uint32 minor;
1002                 int    ret = get_file_version(fsp, driverpath, &major, &minor);
1003                 if (ret == -1) goto error_exit;
1004
1005                 if (!ret) {
1006                         DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1007                         goto error_exit;
1008                 }
1009
1010                 /*
1011                  * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1012                  * for more details. Version in this case is not just the version of the 
1013                  * file, but the version in the sense of kernal mode (2) vs. user mode
1014                  * (3) drivers. Other bits of the version fields are the version info. 
1015                  * JRR 010716
1016                 */
1017                 cversion = major & 0x0000ffff;
1018                 switch (cversion) {
1019                         case 2: /* WinNT drivers */
1020                         case 3: /* Win2K drivers */
1021                                 break;
1022                         
1023                         default:
1024                                 DEBUG(6,("get_correct_cversion: cversion invalid [%s]  cversion = %d\n", 
1025                                         driverpath, cversion));
1026                                 goto error_exit;
1027                 }
1028
1029                 DEBUG(10,("get_correct_cversion: Version info found [%s]  major = 0x%x  minor = 0x%x\n",
1030                                   driverpath, major, minor));
1031         }
1032
1033         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1034                   driverpath, cversion));
1035
1036         close_file(fsp, True);
1037         close_cnum(conn, user->vuid);
1038         unbecome_user();
1039         *perr = WERR_OK;
1040         return cversion;
1041
1042   error_exit:
1043
1044         if(fsp)
1045                 close_file(fsp, True);
1046         
1047         close_cnum(conn, user->vuid);
1048         unbecome_user();
1049         return -1;
1050 }
1051
1052 /****************************************************************************
1053 ****************************************************************************/
1054 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1055                                              struct current_user *user)
1056 {
1057         fstring architecture;
1058         fstring new_name;
1059         char *p;
1060         int i;
1061         WERROR err;
1062
1063         /* clean up the driver name.
1064          * we can get .\driver.dll
1065          * or worse c:\windows\system\driver.dll !
1066          */
1067         /* using an intermediate string to not have overlaping memcpy()'s */
1068         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1069                 fstrcpy(new_name, p+1);
1070                 fstrcpy(driver->driverpath, new_name);
1071         }
1072
1073         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1074                 fstrcpy(new_name, p+1);
1075                 fstrcpy(driver->datafile, new_name);
1076         }
1077
1078         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1079                 fstrcpy(new_name, p+1);
1080                 fstrcpy(driver->configfile, new_name);
1081         }
1082
1083         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1084                 fstrcpy(new_name, p+1);
1085                 fstrcpy(driver->helpfile, new_name);
1086         }
1087
1088         if (driver->dependentfiles) {
1089                 for (i=0; *driver->dependentfiles[i]; i++) {
1090                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1091                                 fstrcpy(new_name, p+1);
1092                                 fstrcpy(driver->dependentfiles[i], new_name);
1093                         }
1094                 }
1095         }
1096
1097         get_short_archi(architecture, driver->environment);
1098         
1099         /* jfm:7/16/2000 the client always sends the cversion=0.
1100          * The server should check which version the driver is by reading
1101          * the PE header of driver->driverpath.
1102          *
1103          * For Windows 95/98 the version is 0 (so the value sent is correct)
1104          * For Windows NT (the architecture doesn't matter)
1105          *      NT 3.1: cversion=0
1106          *      NT 3.5/3.51: cversion=1
1107          *      NT 4: cversion=2
1108          *      NT2K: cversion=3
1109          */
1110         if ((driver->cversion = get_correct_cversion( architecture,
1111                                                       driver->driverpath, user, &err)) == -1)
1112                 return err;
1113
1114         return WERR_OK;
1115 }
1116         
1117 /****************************************************************************
1118 ****************************************************************************/
1119 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
1120                                              struct current_user *user)
1121 {
1122         fstring architecture;
1123         fstring new_name;
1124         char *p;
1125         int i;
1126         WERROR err;
1127
1128         /* clean up the driver name.
1129          * we can get .\driver.dll
1130          * or worse c:\windows\system\driver.dll !
1131          */
1132         /* using an intermediate string to not have overlaping memcpy()'s */
1133         if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1134                 fstrcpy(new_name, p+1);
1135                 fstrcpy(driver->driverpath, new_name);
1136         }
1137
1138         if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1139                 fstrcpy(new_name, p+1);
1140                 fstrcpy(driver->datafile, new_name);
1141         }
1142
1143         if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1144                 fstrcpy(new_name, p+1);
1145                 fstrcpy(driver->configfile, new_name);
1146         }
1147
1148         if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1149                 fstrcpy(new_name, p+1);
1150                 fstrcpy(driver->helpfile, new_name);
1151         }
1152
1153         if (driver->dependentfiles) {
1154                 for (i=0; *driver->dependentfiles[i]; i++) {
1155                         if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1156                                 fstrcpy(new_name, p+1);
1157                                 fstrcpy(driver->dependentfiles[i], new_name);
1158                         }
1159                 }
1160         }
1161
1162         get_short_archi(architecture, driver->environment);
1163
1164         /* jfm:7/16/2000 the client always sends the cversion=0.
1165          * The server should check which version the driver is by reading
1166          * the PE header of driver->driverpath.
1167          *
1168          * For Windows 95/98 the version is 0 (so the value sent is correct)
1169          * For Windows NT (the architecture doesn't matter)
1170          *      NT 3.1: cversion=0
1171          *      NT 3.5/3.51: cversion=1
1172          *      NT 4: cversion=2
1173          *      NT2K: cversion=3
1174          */
1175         if ((driver->version = get_correct_cversion(architecture,
1176                                                     driver->driverpath, user, &err)) == -1)
1177                 return err;
1178
1179         return WERR_OK;
1180 }
1181
1182 /****************************************************************************
1183 ****************************************************************************/
1184 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1185                                                           uint32 level, struct current_user *user)
1186 {
1187         switch (level) {
1188                 case 3:
1189                 {
1190                         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1191                         driver=driver_abstract.info_3;
1192                         return clean_up_driver_struct_level_3(driver, user);
1193                 }
1194                 case 6:
1195                 {
1196                         NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1197                         driver=driver_abstract.info_6;
1198                         return clean_up_driver_struct_level_6(driver, user);
1199                 }
1200                 default:
1201                         return WERR_INVALID_PARAM;
1202         }
1203 }
1204
1205 /****************************************************************************
1206  This function sucks and should be replaced. JRA.
1207 ****************************************************************************/
1208
1209 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1210 {
1211     dst->cversion  = src->version;
1212
1213     fstrcpy( dst->name, src->name);
1214     fstrcpy( dst->environment, src->environment);
1215     fstrcpy( dst->driverpath, src->driverpath);
1216     fstrcpy( dst->datafile, src->datafile);
1217     fstrcpy( dst->configfile, src->configfile);
1218     fstrcpy( dst->helpfile, src->helpfile);
1219     fstrcpy( dst->monitorname, src->monitorname);
1220     fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1221     dst->dependentfiles = src->dependentfiles;
1222 }
1223
1224 #if 0 /* Debugging function */
1225
1226 static char* ffmt(unsigned char *c){
1227         int i;
1228         static char ffmt_str[17];
1229
1230         for (i=0; i<16; i++) {
1231                 if ((c[i] < ' ') || (c[i] > '~'))
1232                         ffmt_str[i]='.';
1233                 else
1234                         ffmt_str[i]=c[i];
1235         }
1236     ffmt_str[16]='\0';
1237         return ffmt_str;
1238 }
1239
1240 #endif
1241
1242 /****************************************************************************
1243 ****************************************************************************/
1244 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, 
1245                                   struct current_user *user, WERROR *perr)
1246 {
1247         NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1248         NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1249         fstring architecture;
1250         pstring new_dir;
1251         pstring old_name;
1252         pstring new_name;
1253         DATA_BLOB null_pw;
1254         connection_struct *conn;
1255         NTSTATUS nt_status;
1256         int ver = 0;
1257         int i;
1258
1259         *perr = WERR_OK;
1260
1261         if (level==3)
1262                 driver=driver_abstract.info_3;
1263         else if (level==6) {
1264                 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1265                 driver = &converted_driver;
1266         } else {
1267                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1268                 return False;
1269         }
1270
1271         get_short_archi(architecture, driver->environment);
1272
1273         /* connect to the print$ share under the same account as the user connected to the rpc pipe */  
1274         /* Null password is ok - we are already an authenticated user... */
1275         null_pw = data_blob(NULL, 0);
1276         conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
1277
1278         if (conn == NULL) {
1279                 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1280                 *perr = ntstatus_to_werror(nt_status);
1281                 return False;
1282         }
1283
1284         /*
1285          * Save who we are - we are temporarily becoming the connection user.
1286          */
1287
1288         push_sec_ctx();
1289
1290         if (!become_user(conn, conn->vuid)) {
1291                 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1292                 pop_sec_ctx();
1293                 return False;
1294         }
1295
1296         /*
1297          * make the directories version and version\driver_name
1298          * under the architecture directory.
1299          */
1300         DEBUG(5,("Creating first directory\n"));
1301         slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1302         mkdir_internal(conn, new_dir);
1303
1304         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1305          * listed for this driver which has already been moved, skip it (note:
1306          * drivers may list the same file name several times. Then check if the
1307          * file already exists in archi\cversion\, if so, check that the version
1308          * info (or time stamps if version info is unavailable) is newer (or the
1309          * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1310          * Otherwise, delete the file.
1311          *
1312          * If a file is not moved to archi\cversion\ because of an error, all the
1313          * rest of the 'unmoved' driver files are removed from archi\. If one or
1314          * more of the driver's files was already moved to archi\cversion\, it
1315          * potentially leaves the driver in a partially updated state. Version
1316          * trauma will most likely occur if an client attempts to use any printer
1317          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1318          * done is appropriate... later JRR
1319          */
1320
1321         DEBUG(5,("Moving files now !\n"));
1322
1323         if (driver->driverpath && strlen(driver->driverpath)) {
1324                 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);      
1325                 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);   
1326                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1327                         NTSTATUS status;
1328                         status = rename_internals(conn, new_name, old_name, True);
1329                         if (!NT_STATUS_IS_OK(status)) {
1330                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1331                                                 new_name, old_name));
1332                                 *perr = ntstatus_to_werror(status);
1333                                 unlink_internals(conn, 0, new_name);
1334                                 ver = -1;
1335                         }
1336                 }
1337                 else
1338                         unlink_internals(conn, 0, new_name);
1339         }
1340
1341         if (driver->datafile && strlen(driver->datafile)) {
1342                 if (!strequal(driver->datafile, driver->driverpath)) {
1343                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);        
1344                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);     
1345                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1346                                 NTSTATUS status;
1347                                 status = rename_internals(conn, new_name, old_name, True);
1348                                 if (!NT_STATUS_IS_OK(status)) {
1349                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1350                                                         new_name, old_name));
1351                                         *perr = ntstatus_to_werror(status);
1352                                         unlink_internals(conn, 0, new_name);
1353                                         ver = -1;
1354                                 }
1355                         }
1356                         else
1357                                 unlink_internals(conn, 0, new_name);
1358                 }
1359         }
1360
1361         if (driver->configfile && strlen(driver->configfile)) {
1362                 if (!strequal(driver->configfile, driver->driverpath) &&
1363                         !strequal(driver->configfile, driver->datafile)) {
1364                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);      
1365                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);   
1366                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1367                                 NTSTATUS status;
1368                                 status = rename_internals(conn, new_name, old_name, True);
1369                                 if (!NT_STATUS_IS_OK(status)) {
1370                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1371                                                         new_name, old_name));
1372                                         *perr = ntstatus_to_werror(status);
1373                                         unlink_internals(conn, 0, new_name);
1374                                         ver = -1;
1375                                 }
1376                         }
1377                         else
1378                                 unlink_internals(conn, 0, new_name);
1379                 }
1380         }
1381
1382         if (driver->helpfile && strlen(driver->helpfile)) {
1383                 if (!strequal(driver->helpfile, driver->driverpath) &&
1384                         !strequal(driver->helpfile, driver->datafile) &&
1385                         !strequal(driver->helpfile, driver->configfile)) {
1386                         slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);        
1387                         slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);     
1388                         if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1389                                 NTSTATUS status;
1390                                 status = rename_internals(conn, new_name, old_name, True);
1391                                 if (!NT_STATUS_IS_OK(status)) {
1392                                         DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1393                                                         new_name, old_name));
1394                                         *perr = ntstatus_to_werror(status);
1395                                         unlink_internals(conn, 0, new_name);
1396                                         ver = -1;
1397                                 }
1398                         }
1399                         else
1400                                 unlink_internals(conn, 0, new_name);
1401                 }
1402         }
1403
1404         if (driver->dependentfiles) {
1405                 for (i=0; *driver->dependentfiles[i]; i++) {
1406                         if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1407                                 !strequal(driver->dependentfiles[i], driver->datafile) &&
1408                                 !strequal(driver->dependentfiles[i], driver->configfile) &&
1409                                 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1410                                 int j;
1411                                 for (j=0; j < i; j++) {
1412                                         if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1413                                                 goto NextDriver;
1414                                         }
1415                                 }
1416
1417                                 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);       
1418                                 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);    
1419                                 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1420                                         NTSTATUS status;
1421                                         status = rename_internals(conn, new_name, old_name, True);
1422                                         if (!NT_STATUS_IS_OK(status)) {
1423                                                 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1424                                                                 new_name, old_name));
1425                                                 *perr = ntstatus_to_werror(status);
1426                                                 unlink_internals(conn, 0, new_name);
1427                                                 ver = -1;
1428                                         }
1429                                 }
1430                                 else
1431                                         unlink_internals(conn, 0, new_name);
1432                         }
1433                 NextDriver: ;
1434                 }
1435         }
1436
1437         close_cnum(conn, user->vuid);
1438         pop_sec_ctx();
1439
1440         return ver == -1 ? False : True;
1441 }
1442
1443 /****************************************************************************
1444 ****************************************************************************/
1445 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1446 {
1447         int len, buflen;
1448         fstring architecture;
1449         pstring directory;
1450         pstring temp_name;
1451         pstring key;
1452         char *buf;
1453         int i, ret;
1454         TDB_DATA kbuf, dbuf;
1455
1456         get_short_archi(architecture, driver->environment);
1457
1458         /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1459          * \\server is added in the rpc server layer.
1460          * It does make sense to NOT store the server's name in the printer TDB.
1461          */
1462
1463         slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1464
1465     /* .inf files do not always list a file for each of the four standard files. 
1466      * Don't prepend a path to a null filename, or client claims:
1467      *   "The server on which the printer resides does not have a suitable 
1468      *   <printer driver name> printer driver installed. Click OK if you 
1469      *   wish to install the driver on your local machine."
1470      */
1471         if (strlen(driver->driverpath)) {
1472         fstrcpy(temp_name, driver->driverpath);
1473         slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1474     }
1475
1476         if (strlen(driver->datafile)) {
1477         fstrcpy(temp_name, driver->datafile);
1478         slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1479     }
1480
1481         if (strlen(driver->configfile)) {
1482         fstrcpy(temp_name, driver->configfile);
1483         slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1484     }
1485
1486         if (strlen(driver->helpfile)) {
1487         fstrcpy(temp_name, driver->helpfile);
1488         slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1489     }
1490
1491         if (driver->dependentfiles) {
1492                 for (i=0; *driver->dependentfiles[i]; i++) {
1493             fstrcpy(temp_name, driver->dependentfiles[i]);
1494             slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1495                 }
1496         }
1497
1498         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1499
1500         DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1501
1502         buf = NULL;
1503         len = buflen = 0;
1504
1505  again:
1506         len = 0;
1507         len += tdb_pack(buf+len, buflen-len, "dffffffff",
1508                         driver->cversion,
1509                         driver->name,
1510                         driver->environment,
1511                         driver->driverpath,
1512                         driver->datafile,
1513                         driver->configfile,
1514                         driver->helpfile,
1515                         driver->monitorname,
1516                         driver->defaultdatatype);
1517
1518         if (driver->dependentfiles) {
1519                 for (i=0; *driver->dependentfiles[i]; i++) {
1520                         len += tdb_pack(buf+len, buflen-len, "f",
1521                                         driver->dependentfiles[i]);
1522                 }
1523         }
1524
1525         if (len != buflen) {
1526                 char *tb;
1527                 
1528                 tb = (char *)Realloc(buf, len);
1529                 if (!tb) {
1530                         DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1531                         ret = -1;
1532                         goto done;
1533                 }
1534                 else buf = tb;
1535                 buflen = len;
1536                 goto again;
1537         }
1538
1539
1540         kbuf.dptr = key;
1541         kbuf.dsize = strlen(key)+1;
1542         dbuf.dptr = buf;
1543         dbuf.dsize = len;
1544         
1545         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1546
1547 done:
1548         if (ret)
1549                 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1550
1551         SAFE_FREE(buf);
1552         return ret;
1553 }
1554
1555 /****************************************************************************
1556 ****************************************************************************/
1557 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1558 {
1559         NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1560
1561         ZERO_STRUCT(info3);
1562         info3.cversion = driver->version;
1563         fstrcpy(info3.name,driver->name);
1564         fstrcpy(info3.environment,driver->environment);
1565         fstrcpy(info3.driverpath,driver->driverpath);
1566         fstrcpy(info3.datafile,driver->datafile);
1567         fstrcpy(info3.configfile,driver->configfile);
1568         fstrcpy(info3.helpfile,driver->helpfile);
1569         fstrcpy(info3.monitorname,driver->monitorname);
1570         fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1571         info3.dependentfiles = driver->dependentfiles;
1572
1573         return add_a_printer_driver_3(&info3);
1574 }
1575
1576
1577 /****************************************************************************
1578 ****************************************************************************/
1579 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1580 {
1581         NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1582
1583         ZERO_STRUCT(info);
1584
1585         fstrcpy(info.name, in_prt);
1586         fstrcpy(info.defaultdatatype, "RAW");
1587         
1588         fstrcpy(info.driverpath, "");
1589         fstrcpy(info.datafile, "");
1590         fstrcpy(info.configfile, "");
1591         fstrcpy(info.helpfile, "");
1592
1593         if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1594                 return WERR_NOMEM;
1595
1596         memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1597         fstrcpy(info.dependentfiles[0], "");
1598
1599         *info_ptr = memdup(&info, sizeof(info));
1600         
1601         return WERR_OK;
1602 }
1603
1604 /****************************************************************************
1605 ****************************************************************************/
1606 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1607 {
1608         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1609         TDB_DATA kbuf, dbuf;
1610         fstring architecture;
1611         int len = 0;
1612         int i;
1613         pstring key;
1614
1615         ZERO_STRUCT(driver);
1616
1617         get_short_archi(architecture, in_arch);
1618
1619         DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1620
1621         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1622
1623         kbuf.dptr = key;
1624         kbuf.dsize = strlen(key)+1;
1625         
1626         dbuf = tdb_fetch(tdb_drivers, kbuf);
1627 #if 0
1628         if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1629 #else
1630         if (!dbuf.dptr) return WERR_ACCESS_DENIED;
1631 #endif
1632         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1633                           &driver.cversion,
1634                           driver.name,
1635                           driver.environment,
1636                           driver.driverpath,
1637                           driver.datafile,
1638                           driver.configfile,
1639                           driver.helpfile,
1640                           driver.monitorname,
1641                           driver.defaultdatatype);
1642
1643         i=0;
1644         while (len < dbuf.dsize) {
1645                 fstring *tddfs;
1646         
1647                 tddfs = (fstring *)Realloc(driver.dependentfiles,
1648                                                          sizeof(fstring)*(i+2));
1649                 if (tddfs == NULL) {
1650                         DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1651                         break;
1652                 }
1653                 else driver.dependentfiles = tddfs;
1654
1655                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1656                                   &driver.dependentfiles[i]);
1657                 i++;
1658         }
1659         if (driver.dependentfiles != NULL)
1660                 fstrcpy(driver.dependentfiles[i], "");
1661
1662         SAFE_FREE(dbuf.dptr);
1663
1664         if (len != dbuf.dsize) {
1665                 SAFE_FREE(driver.dependentfiles);
1666
1667                 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1668         }
1669
1670         *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1671
1672         return WERR_OK;
1673 }
1674
1675 /****************************************************************************
1676 ****************************************************************************/
1677 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1678 {
1679         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1680         TDB_DATA kbuf;
1681         pstring key;
1682         int i;
1683         line[0] = '\0';
1684
1685         slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1686         DEBUG(10,("driver key: [%s]\n", key));
1687         
1688         kbuf.dptr = key;
1689         kbuf.dsize = strlen(key)+1;
1690         if (!tdb_exists(tdb_drivers, kbuf)) return False;
1691
1692         ZERO_STRUCT(info3);
1693         get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1694         
1695     DEBUGADD(10,("info3->name            [%s]\n", info3->name));
1696     DEBUGADD(10,("info3->datafile        [%s]\n", info3->datafile));
1697     DEBUGADD(10,("info3->helpfile        [%s]\n", info3->helpfile));
1698     DEBUGADD(10,("info3->monitorname     [%s]\n", info3->monitorname));
1699     DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1700         for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1701     DEBUGADD(10,("info3->dependentfiles  [%s]\n", info3->dependentfiles[i]));
1702     }
1703     DEBUGADD(10,("info3->environment     [%s]\n", info3->environment));
1704     DEBUGADD(10,("info3->driverpath      [%s]\n", info3->driverpath));
1705     DEBUGADD(10,("info3->configfile      [%s]\n", info3->configfile));
1706
1707         /*pstrcat(line, info3->name);             pstrcat(line, ":");*/
1708         trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1709         pstrcat(line, info3->configfile);
1710     pstrcat(line, ":");
1711         trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1712         pstrcat(line, info3->datafile);
1713     pstrcat(line, ":");
1714         trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1715         pstrcat(line, info3->helpfile);
1716     pstrcat(line, ":");
1717         trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1718         pstrcat(line, info3->monitorname);
1719     pstrcat(line, ":");
1720         pstrcat(line, "RAW");                /*info3->defaultdatatype);*/
1721     pstrcat(line, ":");
1722
1723         for (i=0; info3->dependentfiles &&
1724                  *info3->dependentfiles[i]; i++) {
1725                 if (i) pstrcat(line, ",");               /* don't end in a "," */
1726                 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1727                 pstrcat(line, info3->dependentfiles[i]);
1728         }
1729         
1730         SAFE_FREE(info3);
1731
1732         return True;    
1733 }
1734
1735 /****************************************************************************
1736 debugging function, dump at level 6 the struct in the logs
1737 ****************************************************************************/
1738 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1739 {
1740         uint32 result;
1741         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1742         int i;
1743         
1744         DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1745         
1746         switch (level)
1747         {
1748                 case 3:
1749                 {
1750                         if (driver.info_3 == NULL)
1751                                 result=5;
1752                         else {
1753                                 info3=driver.info_3;
1754                         
1755                                 DEBUGADD(106,("version:[%d]\n",         info3->cversion));
1756                                 DEBUGADD(106,("name:[%s]\n",            info3->name));
1757                                 DEBUGADD(106,("environment:[%s]\n",     info3->environment));
1758                                 DEBUGADD(106,("driverpath:[%s]\n",      info3->driverpath));
1759                                 DEBUGADD(106,("datafile:[%s]\n",        info3->datafile));
1760                                 DEBUGADD(106,("configfile:[%s]\n",      info3->configfile));
1761                                 DEBUGADD(106,("helpfile:[%s]\n",        info3->helpfile));
1762                                 DEBUGADD(106,("monitorname:[%s]\n",     info3->monitorname));
1763                                 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1764                                 
1765                                 for (i=0; info3->dependentfiles &&
1766                                           *info3->dependentfiles[i]; i++) {
1767                                         DEBUGADD(106,("dependentfile:[%s]\n",
1768                                                       info3->dependentfiles[i]));
1769                                 }
1770                                 result=0;
1771                         }
1772                         break;
1773                 }
1774                 default:
1775                         DEBUGADD(1,("Level not implemented\n"));
1776                         result=1;
1777                         break;
1778         }
1779         
1780         return result;
1781 }
1782
1783 /****************************************************************************
1784 ****************************************************************************/
1785 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1786 {
1787         int len = 0;
1788
1789         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1790
1791         if (!nt_devmode) return len;
1792
1793         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1794                         nt_devmode->devicename,
1795                         nt_devmode->formname,
1796
1797                         nt_devmode->specversion,
1798                         nt_devmode->driverversion,
1799                         nt_devmode->size,
1800                         nt_devmode->driverextra,
1801                         nt_devmode->orientation,
1802                         nt_devmode->papersize,
1803                         nt_devmode->paperlength,
1804                         nt_devmode->paperwidth,
1805                         nt_devmode->scale,
1806                         nt_devmode->copies,
1807                         nt_devmode->defaultsource,
1808                         nt_devmode->printquality,
1809                         nt_devmode->color,
1810                         nt_devmode->duplex,
1811                         nt_devmode->yresolution,
1812                         nt_devmode->ttoption,
1813                         nt_devmode->collate,
1814                         nt_devmode->logpixels,
1815                         
1816                         nt_devmode->fields,
1817                         nt_devmode->bitsperpel,
1818                         nt_devmode->pelswidth,
1819                         nt_devmode->pelsheight,
1820                         nt_devmode->displayflags,
1821                         nt_devmode->displayfrequency,
1822                         nt_devmode->icmmethod,
1823                         nt_devmode->icmintent,
1824                         nt_devmode->mediatype,
1825                         nt_devmode->dithertype,
1826                         nt_devmode->reserved1,
1827                         nt_devmode->reserved2,
1828                         nt_devmode->panningwidth,
1829                         nt_devmode->panningheight,
1830                         nt_devmode->private);
1831
1832         
1833         if (nt_devmode->private) {
1834                 len += tdb_pack(buf+len, buflen-len, "B",
1835                                 nt_devmode->driverextra,
1836                                 nt_devmode->private);
1837         }
1838
1839         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1840
1841         return len;
1842 }
1843
1844 /****************************************************************************
1845 ****************************************************************************/
1846 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1847 {
1848         int len = 0;
1849
1850         while (param != NULL) {
1851                 len += tdb_pack(buf+len, buflen-len, "pfdB",
1852                                 param,
1853                                 param->value,
1854                                 param->type,
1855                                 param->data_len,
1856                                 param->data);
1857                 param=param->next;      
1858         }
1859
1860         len += tdb_pack(buf+len, buflen-len, "p", param);
1861
1862         return len;
1863 }
1864
1865
1866 /****************************************************************************
1867 delete a printer - this just deletes the printer info file, any open
1868 handles are not affected
1869 ****************************************************************************/
1870 uint32 del_a_printer(char *sharename)
1871 {
1872         pstring key;
1873         TDB_DATA kbuf;
1874
1875         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1876
1877         kbuf.dptr=key;
1878         kbuf.dsize=strlen(key)+1;
1879
1880         tdb_delete(tdb_printers, kbuf);
1881         return 0;
1882 }
1883
1884 /* FIXME!!!  Reorder so this forward declaration is not necessary --jerry */
1885 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1886 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1887 /****************************************************************************
1888 ****************************************************************************/
1889 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1890 {
1891         pstring key;
1892         char *buf;
1893         int buflen, len;
1894         WERROR ret;
1895         TDB_DATA kbuf, dbuf;
1896         
1897         /*
1898          * in addprinter: no servername and the printer is the name
1899          * in setprinter: servername is \\server
1900          *                and printer is \\server\\printer
1901          *
1902          * Samba manages only local printers.
1903          * we currently don't support things like path=\\other_server\printer
1904          */
1905
1906         if (info->servername[0]!='\0') {
1907                 trim_string(info->printername, info->servername, NULL);
1908                 trim_string(info->printername, "\\", NULL);
1909                 info->servername[0]='\0';
1910         }
1911
1912         /*
1913          * JFM: one day I'll forget.
1914          * below that's info->portname because that's the SAMBA sharename
1915          * and I made NT 'thinks' it's the portname
1916          * the info->sharename is the thing you can name when you add a printer
1917          * that's the short-name when you create shared printer for 95/98
1918          * So I've made a limitation in SAMBA: you can only have 1 printer model
1919          * behind a SAMBA share.
1920          */
1921
1922         buf = NULL;
1923         buflen = 0;
1924
1925  again: 
1926         len = 0;
1927         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1928                         info->attributes,
1929                         info->priority,
1930                         info->default_priority,
1931                         info->starttime,
1932                         info->untiltime,
1933                         info->status,
1934                         info->cjobs,
1935                         info->averageppm,
1936                         info->changeid,
1937                         info->c_setprinter,
1938                         info->setuptime,
1939                         info->servername,
1940                         info->printername,
1941                         info->sharename,
1942                         info->portname,
1943                         info->drivername,
1944                         info->comment,
1945                         info->location,
1946                         info->sepfile,
1947                         info->printprocessor,
1948                         info->datatype,
1949                         info->parameters);
1950
1951         len += pack_devicemode(info->devmode, buf+len, buflen-len);
1952         
1953         len += pack_specifics(info->specific, buf+len, buflen-len);
1954
1955         if (buflen != len) {
1956                 char *tb;
1957                 
1958                 tb = (char *)Realloc(buf, len);
1959                 if (!tb) {
1960                         DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
1961                         ret = WERR_NOMEM;
1962                         goto done;
1963                 }
1964                 else buf = tb;
1965                 buflen = len;
1966                 goto again;
1967         }
1968         
1969
1970         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
1971
1972         kbuf.dptr = key;
1973         kbuf.dsize = strlen(key)+1;
1974         dbuf.dptr = buf;
1975         dbuf.dsize = len;
1976
1977         ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
1978
1979 done:
1980         if (!W_ERROR_IS_OK(ret))
1981                 DEBUG(8, ("error updating printer to tdb on disk\n"));
1982
1983         SAFE_FREE(buf);
1984
1985         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1986                  info->sharename, info->drivername, info->portname, len));
1987
1988         return ret;
1989 }
1990
1991
1992 /****************************************************************************
1993 ****************************************************************************/
1994 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1995 {
1996         NT_PRINTER_PARAM *current;
1997         
1998         DEBUG(108,("add_a_specific_param\n"));  
1999
2000         (*param)->next=NULL;
2001         
2002         if (info_2->specific == NULL)
2003         {
2004                 info_2->specific=*param;
2005         }
2006         else
2007         {
2008                 current=info_2->specific;               
2009                 while (current->next != NULL) {
2010                         current=current->next;
2011                 }               
2012                 current->next=*param;
2013         }
2014
2015         *param = NULL;
2016 }
2017
2018 /****************************************************************************
2019 ****************************************************************************/
2020 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
2021 {
2022         NT_PRINTER_PARAM *current;
2023         NT_PRINTER_PARAM *previous;
2024         
2025         current=info_2->specific;
2026         previous=current;
2027         
2028         if (current==NULL) return (False);
2029         
2030         if ( !strcmp(current->value, param->value) &&
2031             (strlen(current->value)==strlen(param->value)) ) {
2032                 DEBUG(109,("deleting first value\n"));
2033                 info_2->specific=current->next;
2034                 SAFE_FREE(current->data);
2035                 SAFE_FREE(current);
2036                 DEBUG(109,("deleted first value\n"));
2037                 return (True);
2038         }
2039
2040         current=previous->next;
2041                 
2042         while ( current!=NULL ) {
2043                 if (!strcmp(current->value, param->value) &&
2044                     strlen(current->value)==strlen(param->value) ) {
2045                         DEBUG(109,("deleting current value\n"));
2046                         previous->next=current->next;
2047                         SAFE_FREE(current->data);
2048                         SAFE_FREE(current);
2049                         DEBUG(109,("deleted current value\n"));
2050                         return(True);
2051                 }
2052                 
2053                 previous=previous->next;
2054                 current=current->next;
2055         }
2056         return (False);
2057 }
2058
2059 /****************************************************************************
2060  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2061 ****************************************************************************/
2062 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2063 {
2064         NT_PRINTER_PARAM *param = *param_ptr;
2065
2066         if(param == NULL)
2067                 return;
2068
2069         DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2070
2071         SAFE_FREE(param->data);
2072         SAFE_FREE(*param_ptr);
2073 }
2074
2075 /****************************************************************************
2076  Malloc and return an NT devicemode.
2077 ****************************************************************************/
2078
2079 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2080 {
2081 /*
2082  * should I init this ones ???
2083         nt_devmode->devicename
2084 */
2085
2086         char adevice[32];
2087         NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2088
2089         if (nt_devmode == NULL) {
2090                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2091                 return NULL;
2092         }
2093
2094         ZERO_STRUCTP(nt_devmode);
2095
2096         safe_strcpy(adevice, default_devicename, sizeof(adevice));
2097         fstrcpy(nt_devmode->devicename, adevice);       
2098         
2099         fstrcpy(nt_devmode->formname, "Letter");
2100
2101         nt_devmode->specversion      = 0x0401;
2102         nt_devmode->driverversion    = 0x0400;
2103         nt_devmode->size             = 0x00DC;
2104         nt_devmode->driverextra      = 0x0000;
2105         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY |
2106                                        DEFAULTSOURCE | COPIES | SCALE |
2107                                        PAPERSIZE | ORIENTATION;
2108         nt_devmode->orientation      = 1;
2109         nt_devmode->papersize        = PAPER_LETTER;
2110         nt_devmode->paperlength      = 0;
2111         nt_devmode->paperwidth       = 0;
2112         nt_devmode->scale            = 0x64;
2113         nt_devmode->copies           = 1;
2114         nt_devmode->defaultsource    = BIN_FORMSOURCE;
2115         nt_devmode->printquality     = RES_HIGH;           /* 0x0258 */
2116         nt_devmode->color            = COLOR_MONOCHROME;
2117         nt_devmode->duplex           = DUP_SIMPLEX;
2118         nt_devmode->yresolution      = 0;
2119         nt_devmode->ttoption         = TT_SUBDEV;
2120         nt_devmode->collate          = COLLATE_FALSE;
2121         nt_devmode->icmmethod        = 0;
2122         nt_devmode->icmintent        = 0;
2123         nt_devmode->mediatype        = 0;
2124         nt_devmode->dithertype       = 0;
2125
2126         /* non utilisés par un driver d'imprimante */
2127         nt_devmode->logpixels        = 0;
2128         nt_devmode->bitsperpel       = 0;
2129         nt_devmode->pelswidth        = 0;
2130         nt_devmode->pelsheight       = 0;
2131         nt_devmode->displayflags     = 0;
2132         nt_devmode->displayfrequency = 0;
2133         nt_devmode->reserved1        = 0;
2134         nt_devmode->reserved2        = 0;
2135         nt_devmode->panningwidth     = 0;
2136         nt_devmode->panningheight    = 0;
2137         
2138         nt_devmode->private = NULL;
2139         return nt_devmode;
2140 }
2141
2142 /****************************************************************************
2143  Deepcopy an NT devicemode.
2144 ****************************************************************************/
2145
2146 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2147 {
2148         NT_DEVICEMODE *new_nt_devicemode = NULL;
2149
2150         if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2151                 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2152                 return NULL;
2153         }
2154
2155         new_nt_devicemode->private = NULL;
2156         if (nt_devicemode->private != NULL) {
2157                 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2158                         SAFE_FREE(new_nt_devicemode);
2159                         DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2160                         return NULL;
2161         }
2162         }
2163
2164         return new_nt_devicemode;
2165 }
2166
2167 /****************************************************************************
2168  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2169 ****************************************************************************/
2170
2171 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2172 {
2173         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2174
2175         if(nt_devmode == NULL)
2176                 return;
2177
2178         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2179
2180         SAFE_FREE(nt_devmode->private);
2181         SAFE_FREE(*devmode_ptr);
2182 }
2183
2184 /****************************************************************************
2185  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2186 ****************************************************************************/
2187 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2188 {
2189         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2190         NT_PRINTER_PARAM *param_ptr;
2191
2192         if(info == NULL)
2193                 return;
2194
2195         DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2196
2197         free_nt_devicemode(&info->devmode);
2198
2199         for(param_ptr = info->specific; param_ptr; ) {
2200                 NT_PRINTER_PARAM *tofree = param_ptr;
2201
2202                 param_ptr = param_ptr->next;
2203                 free_nt_printer_param(&tofree);
2204         }
2205
2206         SAFE_FREE(*info_ptr);
2207 }
2208
2209
2210 /****************************************************************************
2211 ****************************************************************************/
2212 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2213 {
2214         int len = 0;
2215         int extra_len = 0;
2216         NT_DEVICEMODE devmode;
2217
2218         ZERO_STRUCT(devmode);
2219
2220         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2221
2222         if (!*nt_devmode) return len;
2223
2224         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2225                           devmode.devicename,
2226                           devmode.formname,
2227
2228                           &devmode.specversion,
2229                           &devmode.driverversion,
2230                           &devmode.size,
2231                           &devmode.driverextra,
2232                           &devmode.orientation,
2233                           &devmode.papersize,
2234                           &devmode.paperlength,
2235                           &devmode.paperwidth,
2236                           &devmode.scale,
2237                           &devmode.copies,
2238                           &devmode.defaultsource,
2239                           &devmode.printquality,
2240                           &devmode.color,
2241                           &devmode.duplex,
2242                           &devmode.yresolution,
2243                           &devmode.ttoption,
2244                           &devmode.collate,
2245                           &devmode.logpixels,
2246                         
2247                           &devmode.fields,
2248                           &devmode.bitsperpel,
2249                           &devmode.pelswidth,
2250                           &devmode.pelsheight,
2251                           &devmode.displayflags,
2252                           &devmode.displayfrequency,
2253                           &devmode.icmmethod,
2254                           &devmode.icmintent,
2255                           &devmode.mediatype,
2256                           &devmode.dithertype,
2257                           &devmode.reserved1,
2258                           &devmode.reserved2,
2259                           &devmode.panningwidth,
2260                           &devmode.panningheight,
2261                           &devmode.private);
2262         
2263         if (devmode.private) {
2264                 /* the len in tdb_unpack is an int value and
2265                  * devmode.driverextra is only a short
2266                  */
2267                 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2268                 devmode.driverextra=(uint16)extra_len;
2269                 
2270                 /* check to catch an invalid TDB entry so we don't segfault */
2271                 if (devmode.driverextra == 0) {
2272                         devmode.private = NULL;
2273                 }
2274         }
2275
2276         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2277
2278         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2279         if (devmode.private)
2280                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2281
2282         return len;
2283 }
2284
2285 /****************************************************************************
2286 ****************************************************************************/
2287 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2288 {
2289         int len = 0;
2290         NT_PRINTER_PARAM param, *p;
2291
2292         *list = NULL;
2293
2294         while (1) {
2295                 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2296                 if (!p) break;
2297
2298                 len += tdb_unpack(buf+len, buflen-len, "fdB",
2299                                   param.value,
2300                                   &param.type,
2301                                   &param.data_len,
2302                                   &param.data);
2303                 param.next = *list;
2304                 *list = memdup(&param, sizeof(param));
2305
2306                 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2307         }
2308
2309         return len;
2310 }
2311
2312 static void map_to_os2_driver(fstring drivername)
2313 {
2314         static BOOL initialised=False;
2315         static fstring last_from,last_to;
2316         char *mapfile = lp_os2_driver_map();
2317         char **lines = NULL;
2318         int numlines = 0;
2319         int i;
2320
2321         if (!strlen(drivername))
2322                 return;
2323
2324         if (!*mapfile)
2325                 return;
2326
2327         if (!initialised) {
2328                 *last_from = *last_to = 0;
2329                 initialised = True;
2330         }
2331
2332         if (strequal(drivername,last_from)) {
2333                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2334                 fstrcpy(drivername,last_to);
2335                 return;
2336         }
2337
2338         lines = file_lines_load(mapfile, &numlines);
2339         if (numlines == 0) {
2340                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2341                 return;
2342         }
2343
2344         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2345
2346         for( i = 0; i < numlines; i++) {
2347                 char *nt_name = lines[i];
2348                 char *os2_name = strchr(nt_name,'=');
2349
2350                 if (!os2_name)
2351                         continue;
2352
2353                 *os2_name++ = 0;
2354
2355                 while (isspace(*nt_name))
2356                         nt_name++;
2357
2358                 if (!*nt_name || strchr("#;",*nt_name))
2359                         continue;
2360
2361                 {
2362                         int l = strlen(nt_name);
2363                         while (l && isspace(nt_name[l-1])) {
2364                                 nt_name[l-1] = 0;
2365                                 l--;
2366                         }
2367                 }
2368
2369                 while (isspace(*os2_name))
2370                         os2_name++;
2371
2372                 {
2373                         int l = strlen(os2_name);
2374                         while (l && isspace(os2_name[l-1])) {
2375                                 os2_name[l-1] = 0;
2376                                 l--;
2377                         }
2378                 }
2379
2380                 if (strequal(nt_name,drivername)) {
2381                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2382                         fstrcpy(last_from,drivername);
2383                         fstrcpy(last_to,os2_name);
2384                         fstrcpy(drivername,os2_name);
2385                         file_lines_free(lines);
2386                         return;
2387                 }
2388         }
2389
2390         file_lines_free(lines);
2391 }
2392
2393 /****************************************************************************
2394 get a default printer info 2 struct
2395 ****************************************************************************/
2396 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2397 {
2398         int snum;
2399         NT_PRINTER_INFO_LEVEL_2 info;
2400
2401         ZERO_STRUCT(info);
2402
2403         snum = lp_servicenumber(sharename);
2404
2405         slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2406         slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s", 
2407                  get_called_name(), sharename);
2408         fstrcpy(info.sharename, sharename);
2409         fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2410         fstrcpy(info.drivername, lp_printerdriver(snum));
2411
2412         /* by setting the driver name to an empty string, a local NT admin
2413            can now run the **local** APW to install a local printer driver
2414            for a Samba shared printer in 2.2.  Without this, drivers **must** be 
2415            installed on the Samba server for NT clients --jerry */
2416 #if 0   /* JERRY --do not uncomment-- */
2417         if (!*info.drivername)
2418                 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2419 #endif
2420
2421
2422         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2423
2424         pstrcpy(info.comment, "");
2425         fstrcpy(info.printprocessor, "winprint");
2426         fstrcpy(info.datatype, "RAW");
2427
2428         info.attributes = PRINTER_ATTRIBUTE_SHARED   \
2429                          | PRINTER_ATTRIBUTE_LOCAL  \
2430                          | PRINTER_ATTRIBUTE_RAW_ONLY \
2431                          | PRINTER_ATTRIBUTE_QUEUED ;            /* attributes */
2432
2433         info.starttime = 0; /* Minutes since 12:00am GMT */
2434         info.untiltime = 0; /* Minutes since 12:00am GMT */
2435         info.priority = 1;
2436         info.default_priority = 1;
2437         info.setuptime = (uint32)time(NULL) - 86400;    /* minus 1 day */
2438
2439         /*
2440          * I changed this as I think it is better to have a generic
2441          * DEVMODE than to crash Win2k explorer.exe   --jerry
2442          * See the HP Deskjet 990c Win2k drivers for an example.
2443          */
2444
2445 #if 0 /* JRA - NO NOT CHANGE ! */
2446         info.devmode = NULL;
2447 #else
2448         /*
2449          * We should not return a default devicemode, as this causes
2450          * Win2K to not send the correct one on PCL drivers. It needs to
2451          * see a null devicemode so it can then overwrite the devicemode
2452          * on OpenPrinterEx. Yes this *is* insane :-). JRA.
2453          */
2454         if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2455                 goto fail;
2456 #endif
2457
2458         /* This will get the current RPC talloc context, but we should be
2459            passing this as a parameter... fixme... JRA ! */
2460
2461         if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2462                 goto fail;
2463
2464         *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2465         if (! *info_ptr) {
2466                 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2467                 goto fail;
2468         }
2469
2470         return WERR_OK;
2471
2472   fail:
2473
2474         if (info.devmode)
2475                 free_nt_devicemode(&info.devmode);
2476         return WERR_ACCESS_DENIED;
2477 }
2478
2479 /****************************************************************************
2480 ****************************************************************************/
2481 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2482 {
2483         pstring key;
2484         NT_PRINTER_INFO_LEVEL_2 info;
2485         int             len = 0;
2486         TDB_DATA kbuf, dbuf;
2487         fstring printername;
2488                 
2489         ZERO_STRUCT(info);
2490
2491         slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2492
2493         kbuf.dptr = key;
2494         kbuf.dsize = strlen(key)+1;
2495
2496         dbuf = tdb_fetch(tdb_printers, kbuf);
2497         if (!dbuf.dptr)
2498                 return get_a_printer_2_default(info_ptr, sharename);
2499
2500         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2501                         &info.attributes,
2502                         &info.priority,
2503                         &info.default_priority,
2504                         &info.starttime,
2505                         &info.untiltime,
2506                         &info.status,
2507                         &info.cjobs,
2508                         &info.averageppm,
2509                         &info.changeid,
2510                         &info.c_setprinter,
2511                         &info.setuptime,
2512                         info.servername,
2513                         info.printername,
2514                         info.sharename,
2515                         info.portname,
2516                         info.drivername,
2517                         info.comment,
2518                         info.location,
2519                         info.sepfile,
2520                         info.printprocessor,
2521                         info.datatype,
2522                         info.parameters);
2523
2524         /* Samba has to have shared raw drivers. */
2525         info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2526
2527         /* Restore the stripped strings. */
2528         slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2529         slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
2530                         info.printername);
2531         fstrcpy(info.printername, printername);
2532
2533         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2534 #if 1
2535         /*
2536          * Some client drivers freak out if there is a NULL devmode
2537          * (probably the driver is not checking before accessing 
2538          * the devmode pointer)   --jerry
2539          */
2540         if (!info.devmode)
2541         {
2542                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
2543                         printername));
2544                 info.devmode = construct_nt_devicemode(printername);
2545         }
2546 #endif
2547         len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2548
2549         /* This will get the current RPC talloc context, but we should be
2550        passing this as a parameter... fixme... JRA ! */
2551
2552         nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2553
2554         /* Fix for OS/2 drivers. */
2555
2556         if (get_remote_arch() == RA_OS2)
2557                 map_to_os2_driver(info.drivername);
2558
2559         SAFE_FREE(dbuf.dptr);
2560         *info_ptr=memdup(&info, sizeof(info));
2561
2562         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2563                  sharename, info.printername, info.drivername));
2564
2565         return WERR_OK; 
2566 }
2567
2568 /****************************************************************************
2569 debugging function, dump at level 6 the struct in the logs
2570 ****************************************************************************/
2571 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2572 {
2573         uint32 result;
2574         NT_PRINTER_INFO_LEVEL_2 *info2;
2575         
2576         DEBUG(106,("Dumping printer at level [%d]\n", level));
2577         
2578         switch (level)
2579         {
2580                 case 2:
2581                 {
2582                         if (printer.info_2 == NULL)
2583                                 result=5;
2584                         else
2585                         {
2586                                 info2=printer.info_2;
2587                         
2588                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2589                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2590                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2591                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2592                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2593                                 DEBUGADD(106,("status:[%d]\n", info2->status));
2594                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2595                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2596                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2597                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2598                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2599
2600                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2601                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2602                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2603                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2604                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2605                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2606                                 DEBUGADD(106,("location:[%s]\n", info2->location));
2607                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2608                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2609                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2610                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2611                                 result=0;
2612                         }
2613                         break;
2614                 }
2615                 default:
2616                         DEBUGADD(1,("Level not implemented\n"));
2617                         result=1;
2618                         break;
2619         }
2620         
2621         return result;
2622 }
2623
2624 /****************************************************************************
2625  Get the parameters we can substitute in an NT print job.
2626 ****************************************************************************/
2627
2628 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2629 {
2630         NT_PRINTER_INFO_LEVEL *printer = NULL;
2631         
2632         **printername = **sharename = **portname = '\0';
2633
2634         if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2635                 return;
2636
2637         fstrcpy(*printername, printer->info_2->printername);
2638         fstrcpy(*sharename, printer->info_2->sharename);
2639         fstrcpy(*portname, printer->info_2->portname);
2640
2641         free_a_printer(&printer, 2);
2642 }
2643
2644 /****************************************************************************
2645  Update the changeid time.
2646  This is SO NASTY as some drivers need this to change, others need it
2647  static. This value will change every second, and I must hope that this
2648  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
2649  UTAH ! JRA.
2650 ****************************************************************************/
2651
2652 static uint32 rev_changeid(void)
2653 {
2654         static time_t start_time;
2655         if (start_time == 0)
2656                 start_time = time(NULL);
2657         return (((time(NULL) - start_time)+1)*1000);
2658 }
2659
2660 /*
2661  * The function below are the high level ones.
2662  * only those ones must be called from the spoolss code.
2663  * JFM.
2664  */
2665
2666 /****************************************************************************
2667  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2668 ****************************************************************************/
2669
2670 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2671 {
2672         WERROR result;
2673         
2674         dump_a_printer(printer, level); 
2675         
2676         switch (level)
2677         {
2678                 case 2:
2679                 {
2680                         /*
2681                          * Update the changestamp.  Emperical tests show that the
2682                          * ChangeID is always updated,but c_setprinter is only 
2683                          * incremented on a SetPrinter() call.
2684                          */
2685
2686                         /* ChangeID **must** be increasing over the lifetime
2687                            of client's spoolss service in order for the
2688                            client's cache to show updates */
2689
2690                         printer.info_2->changeid = rev_changeid();
2691
2692                         /*
2693                          * Because one day someone will ask:
2694                          * NT->NT       An admin connection to a remote
2695                          *              printer show changes imeediately in
2696                          *              the properities dialog
2697                          *      
2698                          *              A non-admin connection will only show the
2699                          *              changes after viewing the properites page
2700                          *              2 times.  Seems to be related to a
2701                          *              race condition in the client between the spooler
2702                          *              updating the local cache and the Explorer.exe GUI
2703                          *              actually displaying the properties.
2704                          *
2705                          *              This is fixed in Win2k.  admin/non-admin
2706                          *              connections both display changes immediately.
2707                          *
2708                          * 14/12/01     --jerry
2709                          */
2710
2711                         result=update_a_printer_2(printer.info_2);
2712                         break;
2713                 }
2714                 default:
2715                         result=WERR_UNKNOWN_LEVEL;
2716                         break;
2717         }
2718         
2719         return result;
2720 }
2721
2722 /****************************************************************************
2723  Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2724  We split this out from mod_a_printer as it updates the id's and timestamps.
2725 ****************************************************************************/
2726
2727 WERROR add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2728 {
2729         WERROR result;
2730         
2731         dump_a_printer(printer, level); 
2732         
2733         switch (level)
2734         {
2735                 case 2:
2736                 {
2737                         /*
2738                          * Update the changestamp.  See comments in mod_a_printer()
2739                          * --jerry
2740                          */
2741
2742                         printer.info_2->changeid = rev_changeid();
2743                         printer.info_2->c_setprinter++;
2744
2745                         result=update_a_printer_2(printer.info_2);
2746                         break;
2747                 }
2748                 default:
2749                         result=WERR_UNKNOWN_LEVEL;
2750                         break;
2751         }
2752         
2753         return result;
2754 }
2755
2756 /****************************************************************************
2757  Initialize printer devmode & data with previously saved driver init values.
2758 ****************************************************************************/
2759 static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
2760 {
2761         int                     len = 0;
2762         pstring                 key;
2763         TDB_DATA                kbuf, dbuf;
2764         NT_PRINTER_PARAM        *current;
2765         NT_PRINTER_INFO_LEVEL_2 info;
2766
2767         ZERO_STRUCT(info);
2768
2769         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
2770
2771         kbuf.dptr = key;
2772         kbuf.dsize = strlen(key)+1;
2773
2774         dbuf = tdb_fetch(tdb_drivers, kbuf);
2775         if (!dbuf.dptr)
2776                 return False;
2777
2778         /*
2779          * Get the saved DEVMODE..
2780          */
2781         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2782
2783         /*
2784          * The saved DEVMODE contains the devicename from the printer used during
2785          * the initialization save. Change it to reflect the new printer.
2786          */
2787         ZERO_STRUCT(info.devmode->devicename);
2788         fstrcpy(info.devmode->devicename, info_ptr->printername);
2789
2790         /* 
2791          *      Bind the saved DEVMODE to the new the printer.
2792          */
2793         free_nt_devicemode(&info_ptr->devmode);
2794         info_ptr->devmode = info.devmode;
2795
2796         DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
2797                         info_ptr->printername, info_ptr->drivername));
2798
2799         /* 
2800          * There should not be any printer data 'specifics' already set during the
2801          * add printer operation, if there are delete them. 
2802          */
2803         while ( (current=info_ptr->specific) != NULL ) {
2804                 info_ptr->specific=current->next;
2805                 SAFE_FREE(current->data);
2806                 SAFE_FREE(current);
2807         }
2808
2809         /* 
2810          * Add the printer data 'specifics' to the new printer
2811          */
2812         len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len);
2813
2814         SAFE_FREE(dbuf.dptr);
2815
2816         return True;    
2817 }
2818
2819 /****************************************************************************
2820  Initialize printer devmode & data with previously saved driver init values.
2821  When a printer is created using AddPrinter, the drivername bound to the
2822  printer is used to lookup previously saved driver initialization info, which
2823  is bound to the new printer.
2824 ****************************************************************************/
2825
2826 uint32 set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
2827 {
2828         uint32 result;
2829         
2830         switch (level)
2831         {
2832                 case 2:
2833                 {
2834                         result=set_driver_init_2(printer->info_2);
2835                         break;
2836                 }
2837                 default:
2838                         result=1;
2839                         break;
2840         }
2841         
2842         return result;
2843 }
2844
2845 /****************************************************************************
2846  Pack up the DEVMODE and specifics for a printer into a 'driver init' entry 
2847  in the tdb. Note: this is different from the driver entry and the printer
2848  entry. There should be a single driver init entry for each driver regardless
2849  of whether it was installed from NT or 2K. Technically, they should be
2850  different, but they work out to the same struct.
2851 ****************************************************************************/
2852 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
2853 {
2854         pstring key;
2855         char *buf;
2856         int buflen, len, ret;
2857         TDB_DATA kbuf, dbuf;
2858
2859         buf = NULL;
2860         buflen = 0;
2861
2862  again: 
2863         len = 0;
2864         len += pack_devicemode(info->devmode, buf+len, buflen-len);
2865
2866         len += pack_specifics(info->specific, buf+len, buflen-len);
2867
2868         if (buflen != len) {
2869                 char *tb;
2870                 
2871                 tb = (char *)Realloc(buf, len);
2872                 if (!tb) {
2873                         DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
2874                         ret = -1;
2875                         goto done;
2876                 }
2877                 else buf = tb;
2878                 buflen = len;
2879                 goto again;
2880         }
2881
2882         slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
2883
2884         kbuf.dptr = key;
2885         kbuf.dsize = strlen(key)+1;
2886         dbuf.dptr = buf;
2887         dbuf.dsize = len;
2888
2889         ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
2890
2891 done:
2892         if (ret == -1)
2893                 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
2894
2895         SAFE_FREE(buf);
2896
2897         DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n",
2898                  info->sharename, info->drivername));
2899
2900         return ret;
2901 }
2902
2903 /****************************************************************************
2904  Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer
2905 ****************************************************************************/
2906
2907 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2908 {
2909         uint32 result;
2910         
2911         dump_a_printer(printer, level); 
2912         
2913         switch (level)
2914         {
2915                 case 2:
2916                 {
2917                         result=update_driver_init_2(printer.info_2);
2918                         break;
2919                 }
2920                 default:
2921                         result=1;
2922                         break;
2923         }
2924         
2925         return result;
2926 }
2927
2928 /****************************************************************************
2929  Convert the printer data value, a REG_BINARY array, into an initialization 
2930  DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
2931  got to keep the endians happy :).
2932 ****************************************************************************/
2933
2934 static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode)
2935 {
2936         BOOL       result = False;
2937         prs_struct ps;
2938         DEVICEMODE devmode;
2939
2940         ZERO_STRUCT(devmode);
2941
2942         prs_init(&ps, 0, ctx, UNMARSHALL);
2943         ps.data_p      = (char *)param->data;
2944         ps.buffer_size = param->data_len;
2945
2946         if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
2947                 result = convert_devicemode("", &devmode, &nt_devmode);
2948         else
2949                 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
2950
2951         return result;
2952 }
2953
2954 /****************************************************************************
2955  Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
2956
2957  1. Use the driver's config DLL to this UNC printername and:
2958     a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
2959     b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
2960  2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
2961
2962  The last step triggers saving the "driver initialization" information for
2963  this printer into the tdb. Later, new printers that use this driver will
2964  have this initialization information bound to them. This simulates the
2965  driver initialization, as if it had run on the Samba server (as it would
2966  have done on NT).
2967
2968  The Win32 client side code requirement sucks! But until we can run arbitrary
2969  Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
2970  
2971  It would have been easier to use SetPrinter because all the UNMARSHALLING of
2972  the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
2973  about it and you will realize why.  JRR 010720
2974 ****************************************************************************/
2975
2976 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
2977 {
2978         WERROR        status       = WERR_OK;
2979         TALLOC_CTX    *ctx         = NULL;
2980         NT_DEVICEMODE *nt_devmode  = NULL;
2981         NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
2982         
2983         /*
2984          * Set devmode on printer info, so entire printer initialization can be 
2985          * saved to tdb.
2986          */
2987         if ((ctx = talloc_init()) == NULL)
2988                 return WERR_NOMEM;
2989
2990         if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
2991                 status = WERR_NOMEM;
2992                 goto done;
2993         }
2994         
2995         ZERO_STRUCTP(nt_devmode);
2996
2997         /*
2998          * The DEVMODE is held in the 'data' component of the param in raw binary.
2999          * Convert it to to a devmode structure
3000          */
3001         if (!convert_driver_init(param, ctx, nt_devmode)) {
3002                 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3003                 status = WERR_INVALID_PARAM;
3004                 goto done;
3005         }
3006
3007         /*
3008          * Pack up and add (or update) the DEVMODE and any current printer data to
3009          * a 'driver init' element in the tdb
3010          * 
3011          */
3012         printer->info_2->devmode = nt_devmode;
3013         if (update_driver_init(*printer, 2)!=0) {
3014                 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3015                 status = WERR_NOMEM;
3016                 goto done;
3017         }
3018         
3019         /*
3020          * If driver initialization info was successfully saved, set the current 
3021          * printer to match it. This allows initialization of the current printer 
3022          * as well as the driver.
3023          */
3024         status = mod_a_printer(*printer, 2);
3025         if (!W_ERROR_IS_OK(status)) {
3026                 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3027                                   printer->info_2->printername));
3028         }
3029
3030   done:
3031         talloc_destroy(ctx);
3032         if (nt_devmode)
3033                 SAFE_FREE(nt_devmode->private);
3034         SAFE_FREE(nt_devmode);
3035         printer->info_2->devmode = tmp_devmode;
3036
3037         return status;
3038 }
3039
3040 /****************************************************************************
3041  Update the driver init info (DEVMODE and specifics) for a printer
3042 ****************************************************************************/
3043
3044 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
3045 {
3046         WERROR status = WERR_OK;
3047         
3048         switch (level)
3049         {
3050                 case 2:
3051                 {
3052                         status=save_driver_init_2(printer, param);
3053                         break;
3054                 }
3055                 default:
3056                         status=WERR_UNKNOWN_LEVEL;
3057                         break;
3058         }
3059         
3060         return status;
3061 }
3062
3063 /****************************************************************************
3064  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3065 ****************************************************************************/
3066
3067 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
3068 {
3069         WERROR result;
3070         NT_PRINTER_INFO_LEVEL *printer = NULL;
3071         
3072         *pp_printer = NULL;
3073
3074         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3075
3076         switch (level)
3077         {
3078                 case 2:
3079                 {
3080                         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {