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