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