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